Side-эффект:
Думайте о побочном эффекте как о чем-то, что делает две вещи одновременно.
Например:
Классический пример побочного эффекта:
var i = 1;
var j = i++;
Побочный эффект происходит при i++
. Здесь происходит то, что j
становится 1 , а затем i
увеличивается и становится равным 2. Другими словами, произошли две вещи, и побочным эффектом стало то, что i
стало 2.
Закрытие:
Визуализируйте цепочку ссылок следующим образом: <> <> <> <> <> <> <>.
Представьте себе, что имя этой цепочки ссылок называется scope range . Затем представьте, что все эти ссылки соединяют объекты вместе следующим образом: <> object <> object <> object <>.
Теперь имейте в виду следующее:
(1) Все цепочки областей действия начинаются с глобального объекта .
(2) Когда функция определена, цепочка областей действия для этой функции сохраняется .
(3) Когда вызывается функция, она создает новый объект и добавляет его в цепочку областей действия.
Теперь, пожалуйста, посмотрите на следующий пример:
function counter () { // define counter
var count = 0;
return function () { return count + 1;}; // define anonymous function
};
var count = counter(); // invoke counter
В этом примере, когда определено counter()
, цепочка областей действия для счетчика выглядит следующим образом: <> глобальный объект <>. Затем, когда вызывается counter()
, цепочка областей действия выглядит следующим образом: <> глобальный объект <> счетчик объекта <>. После этого функция без имени (называемая анонимной функцией) внутри счетчика определяется и вызывается. Цепочка областей действия для анонимной функции после ее вызова выглядит следующим образом: <> глобальный объект <> счетчик объекта <> объект анонимной функции <>
Здесь была часть замыкания. Если вы заметили, анонимная функция использует переменную count
, которая была определена вне ее. Причина в том, что анонимная функция может обращаться к любым переменным, определенным в ее цепочке областей действия . Это и есть замыкание, функция вместе со ссылками на любые переменные в цепочке хранимых областей.
Однако в приведенном выше примере, когда функции возвращаются, объекты, созданные при вызове, отбрасываются, так что в действительности нет никакого смысла. Теперь посмотрим на следующее:
function counter () { // define counter
var count = 0;
function f() { return count + 1;}; // define f
return f; // return f
};
var count = counter(); // invoke counter
В этом примере я возвращаю функцию с именем f
и назначаю ее переменной count
. Теперь переменная count
содержит ссылку на всю цепочку областей действия и не сбрасывается. Другими словами, переменная count хранит цепочку областей действия следующим образом: <> глобальный объект <> счетчик объекта <> объект анонимной функции <>. Это сила замыканий, вы можете хранить ссылку на цепочку областей действия и называть ее так: count()
.