Почему для работы setTimeout требуется анонимная функция?

Я читал ответ на StackOverflow здесь, в котором объяснялось, как использовать setTimeout для создания своего рода повторяющегося цикла на веб-странице. Однако мне интересно, почему для setTimeout требуется анонимная функция. Рассмотрим следующий код:

trainingTimer(60,0);

function trainingTimer(duration,c) {
    document.getElementById("timer").innerHTML = "Time left: "+(duration-c);
    if(duration==c) {
        alert("Time is up!");
    }
    else {
        window.setTimeout(trainingTimer(duration,c+1),1000);
    }
}

Я написал это на основе ответа, который я связал выше, однако, когда он запускается, он одновременно выполняет все 60 вызовов trainingTimer и сразу же отображает «Время осталось: 0» на моей веб-странице. Однако, если я изменю

window.setTimeout(trainingTimer(duration,c+1),1000);

и оберните trainingTimer(duration,c+1) в анонимную функцию, например

window.setTimeout(function() {trainingTimer(duration,c+1)},1000);

тогда код работает отлично.

Мне интересно, почему я должен обернуть именованную функцию внутри анонимной функции, чтобы setInterval работал правильно. Спасибо за помощь.


person Charles    schedule 13.05.2014    source источник
comment
trainingTimer(someargs) не возвращает функцию, а setTimeout нужна функция для выполнения.   -  person Kevin B    schedule 14.05.2014
comment
@KevinB Технически функция не нужна...   -  person epascarello    schedule 14.05.2014
comment
я думаю, вроде как window.alert() не нуждается в аргументе.   -  person Kevin B    schedule 14.05.2014
comment
Подробнее о том, что он может взять строку и оценить ее.   -  person epascarello    schedule 14.05.2014


Ответы (3)


Этот

window.setTimeout(trainingTimer(duration,c+1),1000); 

такой же как

var result = trainingTimer(duration,c+1);
window.setTimeout(result,1000); 

Он принимает результат выполненного метода и присваивает его.

И так как метод таймера обучения ничего не возвращает. Ваш код в основном такой

trainingTimer(duration,c+1);
window.setTimeout(undefined, 1000); 
person epascarello    schedule 13.05.2014

Среда выполнения должна оценить список аргументов, переданных любой функции, до ее вызова. Первое, что вы передаете setTimeout в этом коде:

window.setTimeout( trainingTimer(duration,c+1), 1000 );

является результатом вызова функции, а не самой функцией. Обертывание этого в функцию решает эту проблему.

Функция не обязательно должна быть анонимной:

function callTrainingTimer() {
    trainingTimer( duration, c + 1);
}

// ...

window.setTimeout(callTrainingTimer, 1000);

тоже работает.

person Pointy    schedule 13.05.2014

Потому что так работает setTimeout. Его первый параметр — это функция, которую вы хотите запустить через x миллисекунд.

Когда вы делаете:

window.setTimeout(trainingTimer(duration,c+1),1000);

Что вы делаете, так это немедленно запускаете trainingTimer и отправляете возвращаемое значение в setTimeout.

Вам нужно дать ему функцию, поэтому вы делаете:

window.setTimeout(function() {
    trainingTimer(duration, c+1);
},1000);

Есть способ сделать это без функции, но это НЕ рекомендуется.

window.setTimeout('trainingTimer(duration,c+1)', 1000);

Это будет использовать eval() для запуска кода. Это работает вместо передачи функции, но не рекомендуется. eval() небезопасно, не используйте его.

person Rocket Hazmat    schedule 13.05.2014