Возможно ли передать контекст выполнения сразу вызываемого выражения функции

Рассмотрим следующий код:

(function() {
    var a = 5;
    var someFunc = function() { ... };
    function anotherFunc() {
        ...
    };
})();

window.myGlobalObj = {
    init: function() {
        // and somehow here I want to  access to the IIFE context
    }
};

Я хочу иметь контекст выполнения IIFE в моем глобальном объекте. У меня есть доступ к выражению функции и самому объекту, поэтому я могу передать или изменить что-то, чтобы заставить его работать (и нет, я не могу переписать все внутри объекта или функции).

Возможно ли это?

Ответы

Ответ 1

Единственный способ увидеть, насколько это возможно, с помощью eval для имитации динамических областей. Сделайте это (обратите внимание, что IIFE должен быть помещен после глобального объекта):

window.myGlobalObj = {
    init: function() {
        // and somehow here I want to  access to the IIFE context
    }
};

(function() {
    var a = 5;
    var someFunc = function() { ... };
    function anotherFunc() {
        ...
    };

    eval("(" + String(window.myGlobalObj.init) + ")").call(window.myGlobalObj);
})();

Вот ссылка как на использование динамических областей: Возможно ли достичь динамического охвата в JavaScript без использования eval?

Изменить: Я включил пример, демонстрирующий возможности использования динамических областей в JavaScript. Вы можете играть с fiddle.

var o = {
    init: function () {
        alert(a + b === this.x); // alerts true
    },
    x: 5
};

(function () {
    var a = 2;
    var b = 3;

    eval("(" + String(o.init) + ")").call(o);
}());

Ответ 2

"Содержимое" вашего IIFE, т.е. a, someFunc и т.д., являются локальными для этой области действия, поэтому вы можете обращаться к ним только в пределах этой области. Но вы можете назначить window.myGlobalObj внутри IIFE:

(function() {
    var a = 5;
    var someFunc = function() { ... };
    function anotherFunc() {
        ...
    };

    window.myGlobalObj = {
        init: function() {
           // and somehow here I want to  access to the IIFE context
        }
    };

})();

Тогда функция init будет иметь доступ к этим переменным, так как они находятся в области с ее содержанием.

EDIT: если вы не можете переместить определение myGlobalObj в IIFE, единственное, что я могу придумать, это использовать IIFE для создания второго глобального объекта, к которому вы обращаетесь, из myGlobalObj:

(function() {
    var a = 5;
    var someFunc = function() { ... };
    function anotherFunc() {
        ...
    };

    // create a global object that reveals only the parts that you want
    // to be public
    window.mySecondObject = {
       someFunc : someFunc,
       anotherFunc : anotherFunc
    };
})();

window.myGlobalObj = {
    init: function() {
        window.mySecondObject.someFunc();
    }
};

Ответ 3

Нет. Это невозможно. Контекст, к которому вы хотите получить доступ, называется closure и может быть доступен только внутри функции (в вашем случае анонимная функция (IIFE, как вы ее называете)). Для получения дополнительной информации о закрытии следуйте отличным Douglas Crockfords Учебник по языку программирования Javascript.

Вам нужно будет поместить эти атрибуты в какой-то общий объект.