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

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

(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 в моем глобальном объекте. У меня есть доступ к выражению функции и самому объекту, так что я могу передать или изменить что-то, чтобы заставить это работать (и нет, я не могу переписать все внутри объекта или функции).

Это вообще возможно?

3 ответа

Решение

Единственный способ понять, насколько это возможно, - использовать 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. Вы можете играть с скрипкой тоже.

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);
}());

"Содержимое" вашего 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 Функция будет иметь доступ к этим переменным, поскольку они находятся в своей области видимости.

РЕДАКТИРОВАТЬ: если вы не можете переместить определение 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();
    }
};

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

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

Другие вопросы по тегам