Но вар это не для локальной переменной? - PullRequest
1 голос
/ 08 февраля 2012

Это - мой код:

var markers={};
example();

function example() {
    var myFunct = function () {
        alert("hello");
    };

    markers["myIndex"] = myFunct; 
}

markers["myIndex"]();

, как вы можете видеть, myFunct - это "var" (поэтому, когда example() закончится, он будет уничтожен, потому чтоэто локально).Но на самом деле, при доступе к markers["myIndex"]() на функцию ссылаются, и я могу получить к ней доступ.Почему?

Ответы [ 5 ]

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

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

Единственный способ, которым он будет «уничтожен», это если ничто иное не ссылается на него в конце example() или если на него ссылаются только переменные с равной или меньшей областью видимости, при условии, что эти переменные также следовали тем же правилам и не были указаны из внешние переменные.

1 голос
/ 08 февраля 2012

В JavaScript функции являются объектами, как и другие объекты. Когда вы делаете это:

var myFunct = function () {
    alert("hello");
};

... вы создаете функцию и присваиваете ссылку этой функции на переменную myFunct. Затем, когда вы делаете это:

markers["myIndex"] = myFunct; 

... вы назначаете другую ссылку для этой функции на markers["myIndex"]. Таким образом, независимо от всего, что может произойти с переменной myFunct, поскольку markers["myIndex"] все еще имеет ссылку на функцию, функция сохраняется в памяти.

Но отдельно , в вашем вопросе есть и более тонкое недоразумение: вы сказали:

myFunct - это "var" (поэтому, когда example() закончит, он будет уничтожен, потому что он локальный)

Это не так в JavaScript. В JavaScript локальные переменные на самом деле являются свойствами скрытого объекта, называемого (глубокий вдох) объектом привязки переменной из контекста выполнения (давайте просто назовем его «переменным объектом»). Этот объект связан с конкретным вызовом example: он создается при выполнении вызова example. Теперь, в обычном порядке, когда возвращается example, если ничто не имеет какой-либо выдающейся ссылки на объект переменной, тогда вы совершенно правы, что он подходит для сборки мусора. Но в вашем случае что-то имеет ссылку на переменный объект: созданную вами функцию. Когда вы создаете функцию, она получает неявную ссылку на объект переменной для контекста, в котором она была создана, и сохраняет эту ссылку до тех пор, пока функция существует. Таким образом, даже если создаваемая вами функция не ссылается ни на что в объекте переменной для вызова example, она, тем не менее, имеет эту ссылку, и объект переменной не может быть восстановлен до тех пор, пока ничего не имеет ссылки на функция больше. Вот как работают замыкания . Несмотря на вышеприведенный текст, замыкания не сложны , они действительно очень просты, когда вы понимаете, как они работают.

(Я просто отмечу здесь, что некоторые движки JavaScript достаточно тщательно анализируют код, чтобы они могли возвращать переменные объекты, даже когда есть ожидающие замыкания, которые ссылаются на них. В частности, если замыкания [функции] на самом деле не используют какой-либо из свойства объекта переменной, и они не используют eval, тогда механизм может быть в состоянии освободить объект переменной. Например, движок Chrome V8 делает это. Но это оптимизация времени выполнения; 1046 * концепция такая же, как описано выше.)

1 голос
/ 08 февраля 2012

Ссылка от var myFunct на фактический функциональный объект (function() { ... }) действительно будет уничтожена.Но сам объект не будет, так как на него ссылается поле markers.Если нет живых ссылок на объект функции из живых объектов JS, этот объект функции будет пригоден для сборки мусора.

1 голос
/ 08 февраля 2012

Вы присваиваете ссылку на объект функции объекту с более высокой областью действия (если не глобальной областью действия).Таким образом, хотя myFunct будет собирать мусор, функция - нет, так как в объекте маркеров есть другая ссылка на него.

1 голос
/ 08 февраля 2012

Поскольку вы присвоили его глобальной переменной markers из вашей функции example.

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