как стеки памяти работают в JavaScript - PullRequest
2 голосов
/ 20 апреля 2010

Когда у нас есть код вроде:

function a(){
  var x =0;
  this.add=function(){
    alert(x++);
  }
}

   var test = new a();
   test.add(); // alert 0
   test.add(); // alert 1
   test.add(); // alert 2

Как это работает? Разве значение 'x' в a () не должно исчезнуть, как только test = new a () завершится? Стек, содержащий x, тоже должен исчезнуть, верно? Или javascript всегда сохраняет все когда-либо созданные стеки на случай, если на них будут ссылаться в будущем? Но это было бы нехорошо, правда ...?

Ответы [ 2 ]

6 голосов
/ 20 апреля 2010

Слово, которое вы ищете, это «закрытие».

Создание function внутри другой функции дает внутренней функции (скрытую) ссылку на локальную область, в которой выполнялась внешняя функция.

Пока у вас есть копия вашего test, у которого есть явная ссылка на функцию add, а у эта функция имеет неявную ссылку на область, созданную при вызове a конструктор-функция. Эта область видимости имеет явную ссылку на x и любые другие локальные переменные, определенные в функции. (Это включает значение this и значение arguments конструктора - хотя вы не можете получить к ним доступ изнутри add, поскольку собственные функции this / arguments скрывают их.)

Когда вы отпускаете test, интерпретатор JavaScript может отпускать x, потому что нет способа получить ссылку на эту переменную.

4 голосов
/ 20 апреля 2010

То, что вы видите, является эффектом закрытия . Функция, определяемая в другой функции, получает доступ ко всем переменным, например, в области видимости & mdash; даже после того, как внешняя функция вернется. Подробнее здесь , но в основном все переменные (и аргументы) в функции существуют как свойства объекта (называемого «переменным объектом»), связанного с этим вызовом функции. Поскольку функция, которую вы связали с this.add, определена в этом контексте, она имеет постоянную ссылку на этот объект, предотвращая сборку мусора, что означает, что эта функция может продолжать обращаться к этим свойствам (например, переменные и аргументы функции).

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

function foo() {
    var bigarray;
    var x;

    bigarray = /* create a massive array consuming memory */;
    document.getElementById('foo').addEventListener('click', function() {
        ++x;
        alert(x);
    });
}

На первый взгляд, мы видим, что обработчик кликов использует только x. Так что он имеет ссылку только на x, верно?

Неверно, ссылка на переменный объект, который содержит x и bigarray. Таким образом, содержимое bigarray будет также сохраняться, даже если функция их не использует. Это не проблема (и часто это полезно), но она подчеркивает основной механизм. (И если вам действительно не нужно содержимое bigarray в обработчике кликов, вы, возможно, захотите сделать bigarray = undefined; перед возвратом из foo, просто чтобы освободить содержимое.)

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