Динамически присоединить функцию, чтобы предоставить доступ к закрытым переменным - PullRequest
1 голос
/ 05 января 2011

Я пытаюсь динамически назначить обратный вызов моему объекту, и я не могу найти способ сделать это, предоставляя этой функции доступ к закрытым переменным. Я перечислил соответствующий код ниже с комментариями, где я столкнулся со стенами.

Объект Фабрика

function makeObj ( o ) {
                function F() {}
                F.prototype = o;
                return new F();
            }

Модуль

var MODULE = (function(){
   var myMod = {},
       privateVar = "I'm private";
   return myMod;
})();

Различные попытки


myMod.someDynamicFunc = function someDynamicFunc(){
    //privateVar === undefined;
    alert( privateVar );
}
myMod.someDynamicFunc();

myMod.prototype.someDynamicFunc = function someDynamicFunc(){
    //ERROR: Cannot set property 'someDynamicFunc' of undefined
    alert(privateVar);
}
myMod.someDynamicFunc();

В этой попытке я попытался установить сеттер в объекте модуля ... безрезультатно.

var MODULE = (function(){
       var myMod = {},
           privateVar = "I'm private";

           myMod.setDynamicFunction = function ( func ){
              if(func !== undefined && typeof func === "function"){
                //Uncaught TypeError: 
                //         Cannot read property 'dynamicFunction' of undefined
                myMod.prototype.dynamicFunction = func;
                //also tried myMod.dynamicFunction = func;
              }
           }
       return myMod;
    })();

var myModule = makeObject( MODULE );

myModule.setDynamicFunction(function(){
   alert(privateVar);
});

myModule.dynamicFunction();

Я просто неправильно использую JavaScript? Я действительно хотел бы иметь возможность назначать обратные вызовы после инициации объекта. Это возможно?

Ответы [ 2 ]

2 голосов
/ 05 января 2011

Вы не можете получить доступ к закрытой переменной через функцию обратного вызова, установленную динамически (поскольку она не может быть замыканием, если она присоединена позже), но вы можете настроить систему, с помощью которой вы сможете получить доступ к переменной:

var MODULE = (function(){
   var myMod = {},
       privateVar = "I'm private";

   myMod.callback = function(fn) {fn(privateVar);};

   return myMod;
})();

var someDynamicFunc = function(param) {alert(param);};
myMod.callback(someDynamicFunc);

Конечно, это делает его не очень личным, так как это может сделать каждый.Я не понимаю, как вообще было бы возможно иметь «приватную» переменную, к которой вы обращаетесь через динамически присоединенные функции, не позволяя чьим-либо другим динамически присоединенным функциям иметь такую ​​же привилегию (таким образом, делая ее не очень частной).

1 голос
/ 05 января 2011

Полагаю, вы не совсем поняли, как работают замыкания.

Закрытия означают, что области действия всегда имеют доступ к внешней области видимости, которой они были определены дюйм.

function Counter(start) {
    var count = start;


    return {
        increment: function() { // has access to the outer scope
            count++;
        },

        get: function() {
            return count;
        }
    }
}

var foo = new Counter(4);
foo.increment();
foo.get(); // 5

Приведенный выше пример возвращает два замыкания , и функция increment, и get сохраняют ссылку на переменную count, определенную в конструкторе.

Один не может получить доступ к count извне, единственный способ взаимодействия с ним - через две «закрытые» функции.

Помните, что замыкания работают, сохраняя ссылку на их внешние области, поэтому следующее не работает:

var foo = new Counter(4);
foo.hack = function() { // is not getting defined in the same scope that the original count was
    count = 1337;
};

Это не изменит переменную count, которая находится внутри Counter, поскольку foo.hack был не определен в этой области, вместо этого он создаст или переопределит глобальную переменная count.

...