2015-11-01 3 views
1
<!DOCTYPE html> 
<html> 
<body> 
<p>Counting with a local variable.</p> 
<button type="button" onclick="myFunction()">Count!</button> 
<p id="demo"></p> 
<script> 
function Add(x) { 
    this.counter = x; 
    return function() {return this.counter += 1;} 
}; 
var add = Add(0); 

, когда я заменил "var add = Add(0);" с "var add = new Add(0)" выход показывает «NaN». Зачем? и как это работает?Как новое ключевое слово осуществления код JavaScript

function myFunction(){ 
document.getElementById("demo").innerHTML = add(); 
    for each click 1, 2, 3 .... 

} 
</script> 
</body> 
</html> 

ответ

2

new используется для создания нового экземпляра, на основе существующего определения (которые вы храните в Add). Вместо генерируемого экземпляра вы возвращаете функцию, поэтому она не работает так, как вы ожидали.

Эта форма должна работать:

function Add(x) { 
    this.counter = x; 

    this.addOne = function() { 
     return this.counter += 1; 
    } 
} 

var add = new Add(0); 

function myFunction() { 
    document.getElementById("demo").innerHTML = add.addOne(); 
} 

Что касается вашего вопроса о том, почему ваш код возвращается NaN, давайте посмотрим на то, что вы делали:

function Add(x) { 
    this.counter = x; 
    return function() {return this.counter += 1;} 
}; 
var add = new Add(0); 
function myFunction(){ 
    document.getElementById("demo").innerHTML = add(); 
} 

Здесь вы объявляете переменную add и инициализируйте его, используя new Add(0). Во-первых, функция Add объявляет свойство в своей области с именем counter и присваивает ему значение, переданное через параметр с именем x (в данном случае 0). Затем он возвращает функцию. Затем он выходит, больше не требуется, и собирается мусор. Значение, присвоенное объекту counter, отбрасывается, поскольку привязанный к нему к нему вышел из сферы действия.

Теперь у вас есть add как указатель на функцию. Он не имеет свойства с именем counter. Когда вы вызываете функцию add(), она пытается добавить 1 к this.counter. Поскольку this.counter не определен, он автоматически имеет значение undefined.

Если вы попытаетесь добавить число до undefined, вы получите NaN. Поскольку это происходит в заявлении return, возвращается NaN.

2

Разница между Add(0) и new Add(0) заключается в том, что первая вызывает функцию в контексте window. Второй вызывает функцию в новом контексте {}. Тем не менее, в вашей анонимной функции не будет ссылаться на новый контекст {}, поскольку он вызывается в контексте window, поскольку add() - это то же самое, что и window.add().

Для целей отладки, попробуйте добавить некоторые предупреждения или console.logs в вашей функции:

function Add(x) { 
    alert('The context Add was called with is: '+this); 
    this.counter = x; 
    return function() { 
alert('The context the anonymous function was called with is '+this); 
return this.counter += 1;} 
}; 

Тогда вы увидите, что this указывает. Когда window.counter не определено, вы получаете NaN, так как return this.counter += 1; добавляет 1 к undefined, что приводит к NaN.

Что касается решений, один из вариантов является bind функция в контексте вы хотите его называют в:
http://jsfiddle.net/eu9r8pau/4/

Другой вариант воспользоваться затворов, сохраняя ссылку на это:
http://jsfiddle.net/eu9r8pau/5/

Вы также можете переписать код, чтобы что-нибудь попроще:
http://jsfiddle.net/eu9r8pau/6/

+0

Спасибо за примеры. Мне очень полезно понять разницу. На самом деле я ядро ​​программист Java. В отличие от Java, ключевое слово JavaScript «this» на самом деле запутанно! –

0

для добавить еще один вариант для поста и объяснения Дэна Лоу, на этот раз в отношении к названию, например Ор говорит о локальной переменной, которую я понимаю, означает приватную переменную:

<!DOCTYPE html> 
<html> 
<head> 
<meta http-equiv="content-type" content="text/html; charset=UTF-8"> 
</head> 
<body> 
<p>Counting with a local variable.</p> 
<button type="button" onclick="myFunction()">Count!</button> 
<p id="demo"></p> 
<script> 
function Add(x) { 
    var counter = x; 
    return function() {return counter += 1;} 
}; 
var add = new Add(0); 
function myFunction(){ 
    document.getElementById("demo").innerHTML = add(); 
} 
</script> 
</body> 
</html> 

Это, я думаю, классический пример закрытия. Переменная counter остается в рамках функции Add, и только функция для ее увеличения является общедоступной.

Вы можете использовать как можно больше экземпляров Add так, как хотите, и иметь столько независимых счетчиков. Например добавить еще один, начиная с 100:

var bdd = new Add(100); 
function myFunction(){ 
    document.getElementById("demo").innerHTML = add() + "<br />" + bdd(); 
} 

«похожие» правой колонке этой страницы имеет хорошую explanation затворов, пожалуйста, посмотрите.

Смежные вопросы