Javascript 如何在for循环和setTimeout中使用外部初始值设定项?

Javascript 如何在for循环和setTimeout中使用外部初始值设定项?,javascript,typescript,Javascript,Typescript,请看 function main():void{ let loopIndex:number=2; 让动作:字符串[]=[“跳舞”、“走路”、“跑步”、“坐”、“踢”]; 对于(;loopIndexdoAction(actions[loopIndex]),1000; } } 函数doAction(操作:字符串){ console.log(“操作是”+操作); } main(); ///////// 控制台中的输出是 操作正在运行 行动就是静坐 行动就是踢 动作未定义 动作未定义 动作未定义 我

请看

function main():void{
let loopIndex:number=2;
让动作:字符串[]=[“跳舞”、“走路”、“跑步”、“坐”、“踢”];
对于(;loopIndex<5;loopIndex++){
doAction(操作[循环索引]);
setTimeout(()=>doAction(actions[loopIndex]),1000;
}
}
函数doAction(操作:字符串){
console.log(“操作是”+操作);
}
main();
/////////
控制台中的输出是
操作正在运行
行动就是静坐
行动就是踢
动作未定义
动作未定义
动作未定义
我得到了三个未定义的值,希望在控制台的最后三行中打印run-sit-kick的值。
这是一个范围问题吗?我尝试了bind方法。但是,我找不到解决方案。

问题是,当setTimeout中的第一个doAction被称为loopIndex时,它已经等于5,而actions[5]是未知的

解决这个问题的最简单方法是将变量初始化移动到for循环中。这是因为let关键字作用域规则:

for (let loopIndex: number = 2; loopIndex < 5; loopIndex++) {
    doAction(actions[loopIndex]);
    window.setTimeout(() => doAction(actions[loopIndex]), 1000);
}
for(让loopIndex:number=2;loopIndex<5;loopIndex++){
doAction(操作[循环索引]);
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();
function main():void{
let loopIndex:number=2;
让动作:字符串[]=[“跳舞”、“走路”、“跑步”、“坐”、“踢”];
对于(;loopIndex<5;loopIndex++){
doAction(操作[循环索引]);
delayDoAction(动作[loopIndex]);
}
}
函数delayDoAction(操作:字符串){
window.setTimeout(()=>{
行动
}, 1000);
}
函数doAction(操作:字符串){
console.log(“操作是”+操作);
}
main();

或者在doAction函数内部找到增加索引的其他方法。

感谢您提出的闭包建议。它似乎起作用了。我将不得不研究他们一段时间。我不同意你文章中的第一句话。@rickz为了演示第一句话,你可以在执行操作之前在setTimeout回调中添加console.log(startIndex),你将看到5个打印的3次。谢谢你的帮助。我试过你最后的建议。我得到错误:startIndex未定义。我会继续学习。我发现它们很难理解。为了让我的问题更清楚,我将startIndex重命名为loopIndex。我在我的Stackblitz中使用了你的建议,它在那里有效。我还将我的角度项目更改为使用闭包。现在可以了。我还在学习闭包。我还是不明白它为什么有效。你说得对。你的第一句话是正确的。对不起,我怀疑你了。但是,我会将函数的名称从delayDoAction更改为capturedAction。这将描述闭包功能。
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();