Javascript: почему доступ к закрытой переменной может быть медленным - PullRequest
5 голосов
/ 12 февраля 2012

Недавно я прочитал это руководство по производительности Давайте сделаем Интернет быстрее и были озадачены рекомендациями «Избегать ловушек с замыканиями» (как если бы эти советы были даны для пользователей CommonLisp, гдепеременная область видимости является динамической):

var a = 'a';
function createFunctionWithClosure() {
  var b = 'b';
  return function () {
    var c = 'c';
    a;
    b;
    c;
  };
}

var f = createFunctionWithClosure();
f();

при вызове f ссылка a медленнее ссылки b, что медленнее ссылки c.

Совершенно очевидно, что ссылка на локальную переменную c быстрее, чем b , но если iterpreter написан правильно (без динамической области видимости - что-то вродецепочка поиска хеш-таблицы ..) разница в скорости должна быть только предельной.Или нет?

1 Ответ

4 голосов
/ 12 февраля 2012

Ты прав.Современные двигатели JS будут оптимизировать scope chain lookup и prototype chain lookup как много.Значит, AFAIK движок пытается удерживать какую-то хеш-таблицу с узлами доступа внизу.

Это работает, только если нет eval() (подробно или неявно, например, setTimeout) или try-catchили a with statement.Из-за таких конструкций интерпретатор не может быть уверен в том, как получить доступ к данным, и ему нужно «вернуться» в классический scope chain lookup, что на самом деле означает, что он должен пролистать весь родительский контекст variable / activation objects и попытаться разрешитьимя искомой переменной.Этот процесс, конечно, займет больше времени для объектов / имен, которые расположены «далеко» от того места, где был запущен обработанный поиск.Это, в свою очередь, означает, что доступ к данным на global object всегда будет самым медленным.

В вашем фрагменте процесс поиска для a будет выглядеть так:

anonymous function -> Execution Context -> Activation Object (not found)
anonymous function -> Execution Context -> [[ Scope ]] 
    - createFunctionWithClosure
    - global scope
createFunctionWithClosure -> Activation Object (not found)
global scope -> Variable Object (found)

Описанная процедура поиска предназначена для ECMAscript Edition 262, 3-е издание.В ECMAscript edition 5 есть некоторые фундаментальные изменения.

...