https://www.codewars.com/kata/52d3b68215be7c2d5300022f/javascript
Your goal is to write an Event constructor function, which can be used to make event objects.
An event object should work like this:
it has a .subscribe() method, which takes a function and stores it as its handler
it has an .unsubscribe() method, which takes a function and removes it from its handlers
it has an .emit() method, which takes an arbitrary number of arguments and calls all the stored functions with these arguments
As this is an elementary example of events, there are some simplifications:
all functions are called with correct arguments (e.g. only functions will be passed to unsubscribe)
you should not worry about the order of handlers' execution
the handlers will not attempt to modify an event object (e.g. add or remove handlers)
the context of handlers' execution is not important
each handler will be subscribed at most once at any given moment of time. It can still be unsubscribed and then subscribed again
Also see an example test fixture for suggested usage
My answer (NAC)
function Event() {
//your implementation goes here
this.ob = {};
}
Event.prototype.subscribe = function(f) {
if(!this.ob[f.name])
this.ob[f.name] = f;
}
Event.prototype.emit = function(){
for(var func in this.ob) {
this.ob[func] && this.ob[func].call(this, ...Object.values(arguments));
}
}
Event.prototype.unsubscribe = function(f){
if(this.ob[f.name]){
this.ob[f.name] = undefined;
}
}
问题出在哪?
- 数据结构选错了,用对象来存储函数了(应该用数组!)
- 没有理解apply/call(如何区分)、forEach()的用法
- 对arguments对象、prototype、插入删除小能手splice()的不了解
My answer (AC,根据正确答案改的)
function Event() {
//your implementation goes here
this.ob = [];
}
Event.prototype.subscribe = function(f) {
if(!this.ob[f.name])
this.ob.push(f);
}
Event.prototype.emit = function(){
var args = arguments;
this.ob.forEach(function(o){
o.call(this, ...Object.values(args))
});
}
Event.prototype.unsubscribe = function(f){
var index = this.ob.indexOf(f);
if (index !== -1) {
this.ob.splice(index, 1);
}
}
Best answer
class Event {
constructor() {
this.subscribers = new Set();
}
subscribe(func) {
this.subscribers.add(func);
}
unsubscribe(func) {
this.subscribers.delete(func);
}
emit(...args) {
this.subscribers.forEach(s => s(...args));
}
}
好在哪?
- 用了TS的class写法,避免对原型进行处理
- 使用ES6原生对象Set,对函数的操作十分优雅
Recap
call/apply的区别?
接受参数的不同:a
in apply()
for array of args and c
in call()
for comma between args(i.e comma separated arguments)
theFunction.apply(valueForThis, arrayOfArgs)
theFunction.call(valueForThis, arg1, arg2, ...)
splice()为什么是插入删除小能手?
let arrDeletedItems = array.splice(start[, deleteCount[, item1[, item2[, ...]]]])
start:开始index
deleteCount:在该index开始删几个数
items:要插入的item们
网友评论