在Javascript中自动注册所选方法的触发器回调

时间:2012-06-22 15:12:43

标签: javascript jquery javascript-events event-triggers

我需要能够公开一个对象的方法,以便被事件触发器调用。我还想通过提供给定对象的方法及其参数列表来自动注册这些触发器。这是我的(jsfiddle here):

function A() {
}
A.prototype = {
    register: function(cbname, cbargs, context) {
        args = ['context'].concat(cbargs);
        var callback = new Function(args, "context." + cbname + "(" + cbargs.toString() + ");");
        $(document).bind(cbname, callback);
        document.write(callback.toString() + "<br />");
    }
};

function B() {
}
B.prototype = {
    add: function(l, r) {
        document.write(l + r);
    }
};


$(function() {
    var a = new A();
    var b = new B();
    a.register('add', ['l', 'r'], b);
    $(document).trigger('add', [b, 1, 2]);
});​

创建的回调具有正确的代码:function anonymous(context,l,r) { context.add(l,r); }但是在运行时我在控制台中收到错误消息Uncaught TypeError: Object #<Object> has no method 'add'。我做错了什么?

2 个答案:

答案 0 :(得分:1)

我认为触发事件的第一个参数是事件本身。

所以我认为您需要更改注册函数中的行,如下所示:

args = ['evt', 'context'].concat(cbargs);

(jsFiddle:http://jsfiddle.net/hVGcE/3/

答案 1 :(得分:1)

var callback = new Function(args, "context." + cbname + "(" + cbargs.toString() + ");");

使用Function构造函数创建的函数不会为其创建上下文创建闭包;它们总是在窗口环境中运行。它是一种评估形式,因此最好不惜一切代价避免。

function A() {}
A.prototype = {
    register: function (name, context) {
        var callback = function () {
            var args = Array.prototype.slice.call(arguments);
            args.shift();
            context[name].apply(context, args);
        };
        $(document).bind(name, callback);
    }
};

function B() {}
B.prototype = {
    add: function (l, r) {
        console.log(l + r);
    }
};

var a = new A(),
    b = new B();

a.register('add', b);
$(document).trigger('add', [2, 3]); // 5