Существует шаблон, который часто называется «Делегат», который решает эту проблему.
В javascript не слишком причудливая реализация может выглядеть примерно так:
/** class Delegate **/
var Delegate = function(thisRef, funcRef, argsArray) {
this.thisRef=thisRef;
this.funcRef=funcRef;
this.argsArray=argsArray;
}
Delegate.prototype.invoke = function() {
this.funcRef.apply(this.thisRef, this.argsArray);
}
/** static function Delegate.create - convenience function **/
Delegate.create = function(thisRef, funcRef, argsArray) {
var d = new Delegate(thisRef, funcRef, argsArray);
return function() { d.invoke(); }
}
В вашем примере вы бы использовали его так:
this.b = function() {
Z( Delegate.create(this, this.c) );
}
Вы также можете написать функции, которые ожидают получения делегата:
function Z( d ) {
d.invoke();
}
затем, в A
, ваше значение b
становится:
this.b = function() {
var d = new Delegate(this, this.c);
Z( d );
SomeOtherFunc( d );
}
Delegate
просто предоставляет простой, последовательный способ инкапсуляции ссылки this
(которую вы назвали self
) внутри экземпляра объекта, с которым можно обращаться, как с любым другим экземпляром объекта. Это более читабельно и избавляет вас от необходимости загрязнять область вашей функции лишними переменными, такими как self
. У более сложной реализации делегата могут быть свои методы и другое связанное состояние. Также возможно создать делегат таким образом, чтобы он помог минимизировать некоторые проблемы управления памятью, связанные с областью действия (хотя приведенный здесь код определенно не является примером этого).