Подтвердить что ты не робот

Ошибка смешения JavaScript

→ jsFiddle

function f1(){
    var n=999;

    nAdd=function(){n+=1;};

    function f2(){
        alert(n);
    }
    return f2;
}

var result = f1();
var result2 = f1();

result();  // 999
nAdd();
result2(); // 1000
result2(); // 1000
result();  // 999

Я пытаюсь изучить закрытие JavaScript, но приведенный выше код просто запутал меня. Когда вызывается первый раз result(), это 999. Это нормально для меня.

После вызова nAdd() result2() показывает 1000. И я думаю, что это связано с функцией result2(), а функция result() равна функции f1().

Но почему последний result() показывает 999 вместо 1000?

4b9b3361

Ответ 1

Каждый раз, когда вызывается f1(), который создает новое замыкание со своей локальной переменной n.

Однако переменная nAdd является глобальной и поэтому перезаписывается каждый раз, когда вызывается f1(), что означает, что вызов nAdd() будет только добавлять к переменной n в последнем закрытии.

UPDATE: если вы хотите иметь возможность увеличивать значения n в каждом закрытии независимо, вы можете сделать что-то вроде этого:

function f1(){
    var n=999;
    return {
        incrementN : function(){n+=1;},
        getN : function f2(){console.log(n);}
    }
}    
var result = f1();
var result2 = f1();
result.getN(); // 999
result.incrementN();
result2.getN();//999
result2.incrementN();
result2.getN();//1000
result.getN();//1000

То есть, f1() возвращает объект, содержащий два метода, которые не объявлены как глобальные, и что они работают с локальной переменной n из замыкания, к которому они принадлежат.

Ответ 2

Уже есть хорошие ответы, но я думаю, что картина будет полезна для понимания.

enter image description here

Ответ 3

Каждый раз, когда вы вызываете f1(), вы:

  • Создайте новую (локальную) переменную с именем n со значением 999
  • Создайте новую безымянную функцию, назначенную глобальной nAdd, которая изменяет это n (и перезаписывает любую предыдущую функцию, назначенную nAdd)
  • Создайте новую функцию, которую вы возвращаете, которая оповещает значение этого n

Вы дважды вызываете f1(), поэтому вы делаете все это дважды. Во второй раз, когда вы его вызываете, вы перезаписываете nAdd новой функцией, которая изменяет вторую n.

Это дает вам:

  • result(), который предупреждает первый n
  • result2(), который предупреждает второй n
  • nAdd(), который увеличивает второй n

result() в последней строке оповещает 999, потому что он предупреждает о значении первого n (который никогда не увеличивался).

Ответ 4

result и result2 содержат результат различных вызовов f1 и, следовательно, содержат разные экземпляры локальной переменной n. Каждый вызов функции может иметь разные значения для локальных переменных этой функции. Это применяется даже тогда, когда не задействованы блокировки.

Ответ 5

Строка nAdd=function(){n+=1;}; создает глобальную функцию, которая является замыканием внутри f1(). Закрытие также имеет доступ ко всем переменным из области действия созданной им функции. Поэтому каждый раз, когда вы вызываете f1(), он создает новую функцию nAdd(), которая имеет значение n, связанное со значением var n вызова f1().

В вашем коде

var result = f1();
var result2 = f1();
result(); // 999
nAdd();         // Created by "var result2 = f1();" and has the same 'n' value as function in result2
result2();//1000
result2();//1000
result();//999

Ответ 6

результат и результат2 создают два разных замыкания с разными n. Если вы сделаете n глобальной переменной, объявив ее вне функции f1(), вы получите ожидаемый результат, так как в этом случае вы всегда будете обращаться к глобальной переменной n:

var n = 999; функция f1() { Надд = функция() {п + = 1;};
функция f2() { console.log(п);
}
return f2;
}
var result = f1();
var result2 = f1();
результат (а);//999
Надд();
result2();//1000
result2();//1000
результат (а);//1000

Ответ 7

вот так:

var nAdd;
function f1(){
    var n=999;

    nAdd=function(){n+=1;};

    function f2(){
        alert(n);
    }
    return f2;
}

var result = f1();//var nAdd=function(){n+=1;} n=result.n=999

var result2 = f1();//var nAdd=function(){n+=1;} n=result2.n=999

var result3 = f1();//var nAdd=function(){n+=1;} n=result3.n=999

nAdd();

result();  // 999

result2(); // 999

result3(); // 1000

var result = f1();//var nAdd=function(){n+=1;} n=result.n=999

var result2 = f1();//var nAdd=function(){n+=1;} n=result2.n=999

nAdd();

var result3 = f1();//var nAdd=function(){n+=1;} n=result3.n=999


result();  // 999

result2(); // 1000

result3(); // 999

var result = f1();//var nAdd=function(){n+=1;} n=result.n=999

var result2 = f1();//var nAdd=function(){n+=1;} n=result2.n=999

nAdd();

var result3 = f1();//var nAdd=function(){n+=1;} n=result3.n=999
nAdd(); 
nAdd();
nAdd();   

result();  // 999

result2(); // 1000

result3(); // 1002