Основы программирования на JavaScript



              

Замыкание - часть 2


function Animal(name){ this.sleep = function(){ alert(name+' спит: Хрррр'); } }

Можно не заметить этого, но переменная 'name' в функции sleep приходит из родительской функции Animal. Это создает замыкание.

Даже определение простейшей функции может создавать замыкание:

var x = 5; var n = function(){ y=10; return y; }

Здесь также создается замыкание, хотя на первый взгляд это не так. Почему? Когда мы создаем функцию, она получает доступ ко всем переменным в своей текущей области действия, поэтому мы создаем новую ссылку на переменную х.

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

var x = 5; var alertX1 = function(){ alert(x); }

x = 10; var alertX2 = function(){ alert(x); }

alertX1(); alertX2();

Обе функции в этом случае выведут 10. Почему? Потому что они обе указывают на одну и ту же копию х.


Если изменить x в любой точке, то обе функции отразят это. Как это исправить? Проще всего изменить область действия замыкания:

function makeClosure(x){ return function(){ alert(x); } }

var x = 5; var alertX1 = makeClosure(x);

x = 10; var alertX2 = makeClosure(x);

alertX1(); // 5 alertX2(); // 10

Это решает проблему. Если, однако, этот код создавал утечку памяти, то утечка будет существенно больше, чем в предыдущем примере; и также используется больший объем памяти. Оказывается, что в действительности имеется три различных области действия в этом простом примере:


Можно видеть, что переменная х копируется в каждую из двух областей действия. Это связано с тем, что x является строкой или числом. JavaScript всегда передает строки и числа по значению - то есть всегда делается копия переменной. С объектами все происходит иначе. Если х является функцией, массивом или базовым объектом, то в этом случае ссылка в двух наших функциях происходит на одну и ту же копию x и поэтому в результате выводимое сообщение будет одинаковым:




Содержание  Назад  Вперед