2016-04-27 2 views
-3

Я пишу функцию для запуска серии обработчиков кликов с заданным интервалом времени между ними.Почему здесь нет скобок нотации?

function play(step){ 
    var buttons = document.querySelectorAll('.age'); 
    buttons[0].click(); 
    for (var i = 1; i < buttons.length; i++){ 
     setTimeout(function(b){ 
      b.click(); 
     }, 300 + (step*i), buttons[i]); 
    } 
} 

выше функция работает, как задумано, однако, следующая версия, которая мне кажется, что это должно быть эквивалентно, не работает:

function play(step){ 
    var buttons = document.querySelectorAll('.age'); 
    buttons[0].click(); 
    for (var i = 1; i < buttons.length; i++){ 
     setTimeout(function(b){ 
      console.log(i); 
      console.log(b); 
      b[i].click(); 
     }, 300 + (step*i), buttons); 
    } 
} 

Я получаю следующее сообщение об ошибке:

TypeError: Cannot read property 'click' of undefined 

После проверки я обнаружил, что console.log (i) печатает 6. Таким образом, доступ к атрибуту не возникает, пока цикл не закончится, что объясняет ошибку! Но что именно здесь происходит? Я относительно новичок в javascript, но является ли это поведение результатом анонимной функции, действующей как закрытие? Это не похоже на правильное объяснение мне. Это потому, что setTimeout задерживает оценку анонимной функции?

ETA:

Я сделал эксперимент:

 function sleep(ms){ 
      var current = new Date().getTime(); 
      while (current + ms >= new Date().getTime()){}; 
     } 
     function play(step){ 
      var buttons = document.querySelectorAll('.age'); 
      buttons[0].click(); 
      for (var i = 1; i < buttons.length; i++){ 
       setTimeout(function(b){ 
        console.log(b); 
        console.log(i); 
        b[i].click(); 
       }, 300 + (step*i), buttons); 
       sleep(1000); 

      } 
     } 

при запуске игры (200) я получаю то же сообщение об ошибке, поэтому сон (1000) должно быть достаточно времени, чтобы убедиться, что цикл не вышел до первого таймаута, нет?

+0

Что вы заходите на консоль? – SpoonMeiser

+0

@SpoonMeiser Я получаю 5 повторений 6 и кнопок объектов и сообщения об ошибке сверху. –

ответ

2

Это потому, что в каждой итерации (в той же ссылке) переменная in for является одинаковой, а при запуске setTimeout цикл for заканчивается, поэтому переменная i будет последним значением цикла, чтобы исправить это, вы можете создать закрытие с i переменная:

function play(step){ 
    var buttons = document.querySelectorAll('.age'); 
    buttons[0].click(); 
    for (var i = 1; i < buttons.length; i++){ 
     (function(i) { 
      setTimeout(function(b){ 
       console.log(i); 
       console.log(b); 
       b[i].click(); 
      }, 300 + (step*i), buttons); 
     })(i); 
    } 
} 
+0

Будет ли это причиной 'Can not read property 'click' of undefined'? 'b [i]' должен указывать последний элемент в 'NodeList' не' undefined'! – Rayon

+0

@ Rayon переменная i будет увеличена в конце цикла, поэтому она будет равна 'buttons.length', которая будет вызываться одной ошибкой. – jcubic

+0

О, да! Получил это. Спасибо :) – Rayon

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