#javascript #typescript
#javascript #typescript
Вопрос:
Пожалуйста, посмотрите на
https://stackblitz.com/edit/typescript-7hch6s
function main(): void {
let loopIndex: number = 2;
let actions: string[] = ["dance", "walk", "run", "sit", "kick"];
for (; loopIndex < 5; loopIndex ) {
doAction(actions[loopIndex]);
window.setTimeout(() => doAction(actions[loopIndex]), 1000);
}
}
function doAction(action: string) {
console.log("action is " action);
}
main();
/////////
The output in the console is
action is run
action is sit
action is kick
action is undefined
action is undefined
action is undefined
Я получаю три неопределенных параметра, в которых я хочу, чтобы значения run sit kick печатались в последних трех строках консоли.
Это проблема области видимости? Я попробовал метод bind. Но я не смог найти решение.
Ответ №1:
Проблема в том, что к тому времени, когда вызывается первое действие внутри setTimeout, значение loopIndex уже равно 5, а действия [5] неизвестны.
Самый простой способ решить эту проблему — переместить инициализацию переменной в цикл for . Это работает из-за правил определения области действия ключевых слов let:
for (let loopIndex: number = 2; loopIndex < 5; loopIndex ) {
doAction(actions[loopIndex]);
window.setTimeout(() => doAction(actions[loopIndex]), 1000);
}
или вы могли бы использовать закрытие:
function main(): void {
let loopIndex: number = 2;
let actions: string[] = ["dance", "walk", "run", "sit", "kick"];
for (; loopIndex < 5; loopIndex ) {
doAction(actions[loopIndex]);
delayDoAction(actions[loopIndex]);
}
}
function delayDoAction(action: string) {
window.setTimeout(() => {
doAction(action)
}, 1000);
}
function doAction(action: string) {
console.log("action is " action);
}
main();
или найти какой-либо другой способ увеличения индекса внутри функции doAction.
Комментарии:
1. Спасибо, что предложили закрытие. Кажется, это работает. Мне придется некоторое время их изучать. Я не согласен с первым предложением в вашем сообщении.
2. @rickz чтобы продемонстрировать первый оператор, вы можете добавить console.log(startIndex) в обратный вызов setTimeout перед doAction, и вы увидите, что 5 печатается 3 раза.
3. Спасибо, что помогли мне. Я попробовал ваше последнее предложение. Я получаю сообщение об ошибке: startIndex не определен. Я буду продолжать изучать замыкания. Мне трудно их понять.
4. Чтобы прояснить мой вопрос, я переименовал startIndex в loopIndex . Я использовал ваше предложение в своем Stackblitz, и оно там работает. Я также изменил свой проект Angular, чтобы использовать замыкание. Теперь это работает. Я все еще изучаю замыкания. Я до сих пор не понимаю, почему это работает.
5. Вы правы. Ваше первое утверждение верно. Мне жаль, что я сомневался в вас. Но я бы изменил имя вашей функции с delayDoAction на capturedAction. Это описывало бы функциональность закрытия.