Какой срок действия анонимной функции JavaScript? - PullRequest
0 голосов
/ 15 октября 2018

Если я напишу это в глобальной области видимости:

(function(){})();

- создается ли анонимная функция, когда оператор выполняется и уничтожается сразу после выполнения оператора?

, если я пишу это вфункция:

function foo()
{
    var a=1;
    (function(){})();
    a++;
}

Существует ли анонимная функция до тех пор, пока foo не вернется, или существует только во время выполнения этого оператора?

Ответы [ 2 ]

0 голосов
/ 15 октября 2018

Если я напишу это в глобальной области видимости:

(function(){})();

- анонимная функция, созданная, когда оператор выполняется и уничтожается сразу после выполнения оператора?

Как сказал t.niese, шансы, что двигатель полностью оптимизирует эту функцию.Итак, давайте предположим, что в нем есть некоторый код:

// At global scope
(function(){ console.log("Hi there"); })();

Движок не может гарантировать, что этот код не выдаст ошибку (например, если вы заменили console чем-то другим), поэтомуЯ вполне уверен, что он не может просто вставить это.

Теперь ответ: Это зависит.

От уровня языка / спецификации, весь код в модуль компиляции (примерно: скрипт) анализируется при первой загрузке модуля компиляции.Затем эта функция создается, когда код достигает ее в пошаговом исполнении, выполняется после создания (что включает в себя создание контекста выполнения для вызова) и сразу же получает право на сборку мусора по завершении (вместе с контекстом выполнения)потому что ничто не имеет ссылки на это.Но это просто теория / высокоуровневая спецификация.

С точки зрения движка JavaScript:

  • Функция анализируется перед выполнением любого кода.Результат этого анализа (байт-код или машинный код) будет связан с этим выражением функции.Это не ждет, когда выполнение достигнет функции, это делается рано (в фоновом режиме в V8 [движок Google в Chrome и Node.js]).
  • Как только функция была выполнена, и ничто другое не может ссылатьсяк нему:
    • Функция объект и контекст выполнения, связанный с его вызовом, оба имеют право на GC.Когда и как это произойдет, зависит от механизма JavaScript.
    • , который оставляет базовый код функции либо байт-кодом (современные версии V8, использующие Ignition, возможно, другие), либо скомпилированным машинным кодом (более старые версииV8 с использованием Full-codegen, другие).Будет ли механизм JavaScript затем отбрасывать этот байт-код или машинный код, будет зависеть от механизма.У меня нет конкретных знаний о механизмах, выбрасывающих байт-код или машинный код для функций, которые никогда не будут доступны снова.Я действительно знаю, что команда V8 тратит много времени на уменьшение воздействия на память, и подбрасывание этого кода кажется мало повисшим плодом.:-) И что они специально потратили время на работу по оптимизации влияния одноразового кода запуска.

Вот пара статей в блоге V8, которые делаютинтересное чтение:

если я напишу это в функции:

function foo()
{
    var a=1;
    (function(){})();
    a++;
}

Существует ли анонимная функция до тех пор, пока foo не вернется, или просто существует во время выполнения этого оператора?

Давайте предположим,опять же, в этой функции есть console.log, и я прав (это предположениес моей стороны) тот факт, что он опирается на доступную для записи глобальную переменную (console), означает, что он не может быть просто встроен.

Ответ высокого уровня / спецификации такой же: функция анализируется, когдаСкрипт загружается, создается, когда он достигнут, выполняется и имеет право на сборщик мусора, когда он завершен.Но опять же, это просто концепция высокого уровня.

На уровне двигателя, вероятно, все по-другому:

  • Код будет проанализирован , прежде чем любой код вскрипт работает.
  • Байт-код или машинный код, вероятно, генерируется до запуска любого кода в скрипте, хотя я, кажется, вспоминаю что-то из блога V8 о разборе, но не сразу компилирует содержимое функций верхнего уровня.Однако я не могу найти эту статью, если бы она была не только у меня в голове.
  • Когда выполнение достигает функции, для нее создается функция объект вместе с контекстом выполнения(если механизм не уверен, что он может оптимизировать это, не замечая его в коде).
  • После завершения выполнения функция объект и этот контекст выполнения становятся приемлемыми для GC.(Они вполне могли быть в стеке, что делает GC тривиальным, когда foo возвращается.)
  • Основной код, тем не менее, остается в памяти, чтобы использоваться снова (и, если используется достаточно часто, оптимизируется).
0 голосов
/ 15 октября 2018

В этом конкретном случае большинство движков полностью оптимизируют эту функцию, потому что она ничего не делает.

Но давайте предположим, что функция содержит код и действительно выполняется.В этом случае функция будет существовать постоянно, либо как скомпилированный код, либо как байт-код, либо как AST для интерпретатора.

Часть, которая не будет существовать постоянно, - это область действия и возможное созданное замыкание,Область, созданная для этой функции, и замыкание будут существовать только до тех пор, пока функция выполняется или существует ссылка на функцию с определенной связанной областью / замыканием.

Таким образом, комбинация ссылка на функцию + область действия будет выделено во время выполнения оператора (function(){})(); и может быть освобождено после этого оператора.Но скомпилированная версия function(){} может все еще существовать в памяти для последующего использования.

Для механизмов, которые выполняют компиляцию и оптимизацию во времени, функция может даже существовать в разных скомпилированных версиях.

Часть JIT +, оптимизирующая современные движки js, является сложной темой, грубое описание v8 можно найти здесь html5rocks: Компиляция JavaScript :

В V8 полный компилятор работаетна весь код, и начинает выполнять код как можно скорее, быстро генерируя хороший, но не отличный код.Этот компилятор почти ничего не принимает о типах во время компиляции - он ожидает, что типы переменных могут и будут меняться во время выполнения.

Параллельно с полным компилятором V8 перекомпилирует «горячие» функции (то есть функциикоторые запускаются много раз) с оптимизирующим компилятором.[...] В оптимизирующем компиляторе операции спекулятивно встроены (непосредственно помещаются туда, где они вызываются).Это ускоряет выполнение (за счет объема занимаемой памяти), но также позволяет выполнять другие оптимизации.

Таким образом, возможно, что сгенерированный код почти не похож на исходный.

Таким образом, выражение, вызываемое немедленно, может быть даже полностью оптимизировано с помощью встраивания.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...