2013-08-26 6 views
5

По крайней мере, это то, что я думаю, что это произойдет в этом случае:JavaScript SetTimeout не может получить доступ к переменной функции

function MyFunc() { 
    var people = Array({name: 'Alex', age: 25}, {name: 'Ellen', age: 43}); 
    for (var i=0; i<people.length; i++) { 
     setTimeout(function() { ShowIt(people[i].name) }, 1000); // !!! 
    } 
} 

function ShowIt(name) { 
    alert(name); 
} 

Я получаю эту ошибку Uncaught TypeError: Cannot read property 'name' of undefined, поэтому он выглядит как внутри функции setTimeout слушателя переменная people не доступны. Почему и как я могу это исправить?

+0

Это очень распространенная ошибка, см. Этот вопрос: http://stackoverflow.com/questions/5226285/settimeout-in-a-for-loop-and-pass-i-as-value –

+1

Нет, это означает что 'people [i]' не определен. Если «люди» не были в сфере охвата, вы получили бы что-то вроде «Uncaught ReferenceError: люди не определены». –

ответ

21

Фактически Люди массив в порядке. Что происходит, так это то, что ваш i фактически равен 2, и в массиве нет третьего элемента. Вот почему вы получаете эту ошибку. Вот решение:

function MyFunc() { 
    var people = Array({name: 'Alex', age: 25}, {name: 'Ellen', age: 43}); 
    for (var i=0; i<people.length; i++) { 
     (function(i) { 
      setTimeout(function() {    
       ShowIt(people[i].name) 
      }, 1000); 
     })(i); 
    } 
} 

function ShowIt(name) { 
    console.log(name); 
} 

MyFunc(); 

Вот является jsfiddle http://jsfiddle.net/krasimir/XDfLu/2/

Длинный ответ: когда вы используете SetTimeout вы передаете функцию к нему. Эта функция называется в будущем, и то, что вы там делаете, также выполняется в будущем. В этот момент (будущий) ваш i больше не 0 или 1. Это фактически 2, потому что ваш цикл закончился. В предоставленном решении используется дополнительное закрытие для создания еще одной области/контекста. И как только функция, переданная в setTimeout, называется, она ищет переменную i. В его сфере нет такой вещи, поэтому она идет на один уровень вверх. И есть фактическое значение, которое нам нужно.

+0

Уход за разъяснением решения? Что это такое и почему он решает проблему? –

+0

Ответ отредактирован. (Я не уверен, что я объяснил это достаточно хорошо). – Krasimir

+0

Почти. Даже если вы добавили вызов функции, не имеет значения, является ли функция закрытием или нет. Важно только то, что функция выполняется и создает через нее новую область. –

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