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

4

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

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

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

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

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

Выражение функции немедленного вызова @Tomas kapa
какой IIFE? Пожалуйста, будьте ясны TMS
показать пример того, что вы имеете в виду под «доступом к контексту IIFE». Как бы вы получили к нему доступ. TMS
Если вы не можете перенести его содержимое или изменить его, тогда вы просто не сможете этого сделать. Zirak
@Tomas, вызовите someFunc, anotherFunc, используйте переменную «a». Ilya Tsuryev

Ваш Ответ

3   ответа
0

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

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

С вашим ответом вы практически показали, что я был прав - это невозможно (within reasonably sane code).
@AaditMShah, это действительно было бы плохой практикой! Я бы назвал это грязным хаком и запретил бы его. Кстати, использование eval в jQuery для синтаксического анализа JSON считается большим недостатком, и jQuery подвергается критике за это. Вот почему лучше всего использоватьDouglas Crockford's json2.js для этой цели.
Я извиняюсь. Как именно мой код может причинить вред? Если вы сможете доказать мне в разумных пределах, что есть лучший способ решить эту проблему без использованияeval тогда, пожалуйста, пообещай мне. Я не вижу, как использоватьeval в этом случае может привести к небезопасному коду. Не говорите мне, что я не прав. Покажите мне с тестовым примером.
На самом деле это возможно. Все, что вам нужно сделать, это моделировать динамические области в JavaScript, используяeval, я знаю этоeval считается злом, но бывают случаи, когда это необходимо. Даже JQuery используетeval, Имитация динамических областей в JavaScript - один из тех случаев, когда его действительно безопасно использоватьeval, Вы можете прочитать больше об этом здесь:Is it possible to achieve dynamic scoping in JavaScript without resorting to eval?
Это не очень плохая практика. Там очень много страха среди программистов, когда дело доходит доeval и в большинстве случаев это связано с тем, что программисты не знают, как это вредно. Однако в правильных руках это безопасный и мощный инструмент. Подумайте об этом - если это действительно так плохо, то почему бы вообще не удалить его из языка? Это все еще существует в EC5. С помощьюeval для моделирования динамических областей является одним из тех случаев, когдаeval не зло В этом случае использования невозможно сломать существующий код - если только программист не умышленно испортит то, чего, по всей вероятности, никогда не будет.
2

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?

Edit: Я включил пример, чтобы продемонстрировать мощь использования динамических областей в 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);
}());
@ Stonerain, вы только что узнали довольно неприятную вещь. Избегай это! Мастера, такие как Дуглас Крокфорд, недовольны Эвалом. Код ужасен, труден для понимания и отладки, неэффективен и создает другие опасности. Использование его для этой цели является злоупотреблением.
@Aadit, спасибо заlink you posted, Я могу только согласиться с этим:"All such unnecessary uses of eval add to a maintenance hell. Refactoring tools are thrown off. Searching for code is hard. Unanticipated effects of those evals are legion."
Рад помочь. Существует множество хаков, которые можно использовать, если вы хотите больше узнать оeval и как это можно безопасно использовать. Например, вы можете реализоватьpointers в JavaScript с помощьюeval.
@ Томас, я думаю, что это слишком резко. Функцияeval сам Дуглас Крокфорд не осуждает себя. Это неправильное использование этой функции программистами-любителями, что вызывает проблемы. Большинство случаев использованияeval может быть достигнуто без этого. Тем не менее, есть некоторые случаи использования, которые действительно требуютeval, При правильном использованииeval это безопасный инструмент. Я говорил это раньше, и я скажу это снова - большинствоfear относительноeval только из-за невежества. Не винитеeval для плохих программ.
Хотя я на самом деле не буду использовать такую схему в приложении, но это было очень интересно, узнал что-то новое! Ilya Tsuryev
2

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();
    }
};
Да, вам нужно перечислить "общедоступный" из них. Но обратите внимание, что «общедоступный» Сами они будут иметь доступ к «частным» из них.
Хорошо извини Я обновил свой ответ единственной вещью, о которой я могу думать ...
Теперь это будет работать, но я не могу переписать все внутри объекта (или в этом случае внутри IIFE). Ilya Tsuryev
@ Редактировать: я должен был бы перечислить все переменные и функции, к которым я хочу получить доступ, верно? :( Ilya Tsuryev

Похожие вопросы