2012-06-22 4 views
1

Мне нужно уметь выставлять методы одного объекта, вызываемые триггерами событий. Я также хочу автоматически зарегистрировать эти триггеры, предоставив список методов и их аргументы для данного объекта. Вот что у меня есть (jsfiddle here):Автоматически регистрировать триггерные обратные вызовы для выбранных методов в Javascript

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'. Что я делаю не так?

ответ

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

Функции, созданные конструктором Function не создают закрытие их контекстов создания; они всегда запускаются в контексте окна. И это форма eval, поэтому лучше избегать любой ценой.

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 
+0

Спасибо, это намного лучший способ. Я думал, что различие между данными и кодом размыто в этом случае в javascript, есть ли у вас информация о производительности вызовов 'Function'? – Dreen

+1

http://javascriptweblog.wordpress.com/2010/04/19/how-evil-is-eval/ – jasssonpet

1

Я считаю, что первым аргументом инициируемого события является само событие.

Так что я думаю, что вам нужно изменить строку в функции регистра следующим образом:

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

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