JAVASCRIPT:尝试在自定义事件调度程序上创建hasCallbackFor函数

时间:2017-10-18 20:53:27

标签: javascript event-handling event-listener

我正在进行一项练习,现在正在创建一个自定义事件调度程序。

我得到了一堆测试用例,我在我的事件监听器对象上创建了一个名为hasCallbackFor(name,callback)的方法。从我可以收集的内容来看,hasCallbackFor函数应该在我创建的对象上取一个键的名称,而callback是一个位于该键的数组中的函数。它应该检查该功能是否存在。我完全迷失了如何做到这一点,感觉我已经尝试了一切。

这是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个小时了,并希望对此有任何见解。谢谢!

1 个答案:

答案 0 :(得分:1)

在这种情况下,函数名称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 ,不要将scope发送到addEventListener

//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');

两者都有效。