Показать сообщение отдельно
  #29 (permalink)  
Старый 21.09.2009, 18:07
Профессор
Отправить личное сообщение для Dmitry A. Soshnikov Посмотреть профиль Найти все сообщения от Dmitry A. Soshnikov
 
Регистрация: 25.02.2008
Сообщений: 707

Сообщение от Riim
если внутри этой функции создать переменную, одноименную с той, что запомнена, то она как бы экранируется
Да, "экранируется", на этом принципе и работает Scope chain.

Т.е. одноимённые переменные (а также, декларации функций и формальные параметры) более глубокого контекста, разрешаются (определяются) раньше, чем переменные с тем же именем, но в контексте выше. Цепь областей видимости контекста (Scope chain) при нахождении в коде переменной, опрашивается интерпретатором от самого глубого звена цепи вверх до глобального объекта (и, в некоторых реализациях, прототипа глобального объекта).

var a = 10;
function A() {
  var a = 20;
  function B() {
    var a = 30;
    alert(a); // найдено сразу в AO(контекста B)
  }
}


Если бы переменная "а" была объявлена один раз (глобально), то при alert(a) из внутренней функции "B", она бы разрешалась по цепи (Scope chain контекста функции "B"):

1. AO(контекста "B") - (нет) ->
2. AO(контекста "А") - (нет) ->
3. VO(Global) === Global - (да) - 10


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

С другой стороны, одна вложенная функция может не иметь свободных переменных, а вложенная во вложенную может, поэтому, надо запоминать всегда, получается:

function A() {
  var a = 10;
  function B() { // нужен ли этой функции Scope A?
    function C() {
      alert(a); // если B не запомнит Scope A, функция С не найдёт "а"
    }
  }
}


Но, повторю, по идее, может быть проведена оптимизация на уровне реализации.

Поэтому, все функцию при создании запоминаю лексический контекст (т.е. Scope chain этого контекста), в котором они порождены, отсюда - все функции - замыкания. Функция может быть ни разу не запущена, но [[Scope]] уже в неё записался.

Но, стандарт описывает предложение по оптимизации - объединённые объекты:

function a() {
  function b(z) {
    return z * z;
  }
  return b;
}
 
var x = a();
var y = a();


Т.к. [[Scope]] функций x и y - не различим (и вообще, оба объекты - не различимы), реализация вправе использовать объединённые объекты в этом случае, или даже - использовать один объект. Поэтому, не всегда внутренняя функция будет создаваться каждый раз разная.
__________________
Тонкости ECMAScript

Последний раз редактировалось Dmitry A. Soshnikov, 21.09.2009 в 18:21.
Ответить с цитированием