Вопрос по замыканиям
Добрый вечер друзья, возник вопрос, скорей даже не вопрос, а полная неразбериха по теме замыканий (недавно в JS). Что бы без длинных предысторий, сразу покажу код (взял из Википедии):
function createCounter() {
var numberOfCalls = 0;
return function() {
return ++numberOfCalls;
}
}
var fn = createCounter();
fn(); //1
fn(); //2
fn(); //3
Я понимаю, что этот код делает, но абсолютно не понимаю каким образом. Почему при вызове функции createCounter() не обнуляется переменная numberOfCalls? Зачем нужно копировать ссылку на функцию в переменную fn, почему ее нельзя вызвать напрямую? Сам по себе, этот код меня не волнует, но это самый простой пример замыкания, который я, к сожалению, не могу понять. Я бы был очень благодарен, если бы вы подробно объяснили мне ситуацию, как это все считывает интерпретатор. |
Цитата:
Цитата:
|
Цитата:
return ++numberOfCalls; При каждом вызове функции, выводит увеличенный на единицу (по сравнению с предыдущим вызовом) результат, то есть - не обнуляется. |
При вызове функции createCounter обнуляется. Она у вас только один раз вызывается.
|
Цитата:
|
Вот так будет работать как вы хотите, только это не имеет смысла))
function createCounter() {
var numberOfCalls = 0;
return function() {
return ++numberOfCalls;
}
}
var fn = createCounter;
fn()(); //1
fn()(); //1
fn()(); //1
|
Цитата:
|
Цитата:
function() {
return ++numberOfCalls;
}
Спасибо большое, вы очень помогли! Если бы еще понять вот этот синтаксис, fn()(), который все таки вызывает фукцию createCounter(), но я думаю, это уже не так проблематично. |
var fn = createCounter; Вот в чем дело, лол.) А по поводу fn()() - ты это сколько угодно:
function џ() {
return function() {
return function() {
return function() {
return function() {
return function() {
return function() {
return function() {
alert('lol')
}
}
}
}
}
}
}
}
џ()()()()()()()()
хотя всё это фигнестрадание) |
Цитата:
|
Цитата:
function createCounter(){
var numberOfCalls = 0;
return function(){
return ++numberOfCalls;
};
};
var fn1 = createCounter();
fn1(), fn1();
var fn2 = createCounter();
fn2();
alert( fn1() ); // Ведь 3, а не 2
Aetae, как-то жестоко.:) Так по-приличнее, по-моему:
function џ(){
var count = 1;
return function(){
if(++count === 7) return 'lol';
return arguments.callee;
};
};
alert( џ()()()()()()() );
|
А вот еще, хотелось бы еще больше прояснить ситуацию:
Что происходит с переменной numberOfCalls? То есть, как я понимаю, у нас выходит 3 области видимости [scope1] - глобальная, [scope2] - область функции createCounter, [scope3] - вложенная функция. После выхода из функции все эти области остаются жить благодаря замыканию, самое интересное вот что: Переменная numberOfCalls копируется и используется как свойство [scope3], или же мы просто получаем ссылку на [scope2].numberOfCalls(условно), и уже манимулируем собственно ею. Я подозреваю, что копируется (или же у меня в голове просто полная каша), а вот что было бы с объектом? |
Цитата:
|
Sweet,
Ну так фишка то в использовании)):
function џ(b) {
return function(a) {b=b|a;
return function(a) {b=b&a;
return function(a) {b/=a;
return function(a) {b-=a;
return function(a) {b*=a;
return function(a) {b+=a;
return function(a) {b='Результат:'+a;
alert(b)
}
}
}
}
}
}
}
}
џ(4)(5)(2)(4)(7)(9)(2)(1)
Но опять же это бессмысленно) |
Цитата:
Цитата:
|
Цитата:
UPD: Goodfella, извините, но мой мозг не способен переварить этот поток мыслей - я просто не понимаю, что Флэнаган пытается втереть:) Нельзя по утрам так людей грузить:) |
Цитата:
|
Цитата:
function createCounter() {
var numberOfCalls = 0;
alert(numberOfCalls);
return function() {
alert(numberOfCalls);
return ++numberOfCalls;
}
}
var fn = createCounter();
fn(); //Выводит сообщение "0", "0", все ясно, первый вызов.
fn(); //Вызывается только вложенная функция, alert выводит "1", опять же окей.
createCounter(); //Вызывается вся функция, переменная "numberOfCalls" обнулена, alert объемлющей функции выводит "0", годиться.
fn(); //Вызывается опять только вложенная, хотя, по идее "numberOfCalls" был обнулен, alert вывел "2", вот это - не понятно.
|
При втором вызове новый [scope2] создаётся.
|
Цитата:
|
Нет, он замкнут на новосозданную функцию.
function createCounter() {
var i=99;
var j='txt'
return function(a) {
alert(eval(a||'"none"')) //i и j нигде не упоминаются
}
}
var fn = createCounter();
fn();
fn('i');
fn('j');
Вызывая же createCounter() второй раз вы ничего не обнуляете - это уже совершенно другая функция с своим scope. |
| Часовой пояс GMT +3, время: 23:08. |