我现在正在做一个练习,创建一个自定义事件调度器。
我收到了一堆测试用例,我一直在为我的事件侦听器对象创建一个名为hasCallbackFor(name,callback)的方法。据我所知,hasCallbackFor函数应该取我正在创建的对象上的一个键的名称,回调是位于该键的数组中的一个函数。它应该检查该函数是否存在。我完全不知道该怎么做,感觉自己什么都试过了。
这是hasCallbackFor函数的测试用例:
var shouldReturnFalseHasCallBackForIfMethodsNotAdded = function () {
testObj = {};
var scope = {
executeSuccess: true
}
var testFunction = function () {
if (this.executeSuccess) {
success1 = true;
}
}
EventDispatcher.mixin(testObj);
testObj.addEventListener('test', testFunction, scope);
testObj.dispatchEvent('test');
assert(testObj.hasCallbackFor("test", testFunction), 'should have callback registered for test event');
assert(!testObj.hasCallbackFor("test", function () {}), 'should have no callback');
console.log('shouldReturnFalseHasCallBackForIfMethodsNotAdded: success')
}
这是我的addEventListener函数:
/**
* @param {string} name
* @param {function} callback
* @param {Object} opt_scope
*/
addEventListener: function (name, callback, opt_scope) {
if(!EventDispatcher.myObject[name]) {
EventDispatcher.myObject[name] = [];
}
if(opt_scope) {
var bound = callback.bind(opt_scope);
EventDispatcher.myObject[name].push(bound);
} else {
EventDispatcher.myObject[name].push(callback);
}
},
这是我的dispatchEvent函数:
/**
* @param {string} name
*/
dispatchEvent: function (name) {
EventDispatcher.myObject[name].forEach(function(value) {
value();
});
},
对于我的hasCallbackFor函数,我正在尝试使用
/**
* @param {string} name
* @param {function} callback
* @return {boolean}
*/
hasCallbackFor: function (name, callback) {
return EventDispatcher.myObject[name].includes(callback);
},
此功能使的测试用例失败
assert(testObj.hasCallbackFor("test", testFunction), 'should have callback registered for test event');
我已经完全不知道为什么了。我已经盯着这个代码看了大约3个小时了,如果有任何关于这方面的见解,我将不胜感激。非常感谢。
在这种情况下,函数名testFunction
是代码的地址
让我们考虑一个小例子:
var arr = [];
var foo = function(e){return true;};
arr.push(foo);
console.log(arr.includes(foo));//true
var bar = foo.bind('something');
arr.push(bar);
arr.includes(bar);//true
arr.includes(foo.bind('something'));//false .bind creates a new function every time
//The worst case:
arr.push(function(e){return true;});//anonymous function is lost forever
console.log(arr.includes(function(e){return true;}));//false
回到OP。所以问题就在这里:
var bound = callback.bind(opt_scope);//creates a new function with a new address
EventDispatcher.myObject[name].push(bound);
我提供两种解决方案:
从addEventListener
返回功能
addEventListener: function (name, callback, opt_scope) {
if(!EventDispatcher.observable[name]) {
EventDispatcher.observable[name] = [];
}
if (opt_scope) {
var bound = callback.bind(opt_scope);
EventDispatcher.observable[name].push(bound);
return bound;
} else {
EventDispatcher.observable[name].push(callback);
return callback;
}
}
并且在shouldReturnFalseHasCallBackForIfMethodsNotAdded
中调用这样的函数:
var foo = testObj.addEventListener('test', testFunction, scope);
// ^^^
testObj.dispatchEvent('test');
assert(testObj.hasCallbackFor("test", foo), 'should have callback registered for test event');
// ^^^
绑定shouldReturnFalseHasCallBackForIfMethodsNotAdded
中的函数,不向addEventListener
发送scope
//addEventListener is the same as in OP
var foo = testFunction.bind(scope);
testObj.addEventListener('test', foo, null);
testObj.dispatchEvent('test');
assert(testObj.hasCallbackFor("test", foo), 'should have callback registered for test event');
两者都有效。