对于

这个对于语句创建一个由三个可选表达式组成的循环,这些可选表达式用括号括起来并用分号分隔,后跟一个语句(通常是块语句)在循环中执行。

试试看

语法

js型
for(初始化;条件;事后考虑)陈述
初始化 可选

表达式(包括赋值表达式)或变量声明在循环开始之前计算一次。通常用于初始化计数器变量。此表达式可以选择使用变量关键字。用声明的变量变量不是循环的局部,即它们在同一范围内对于循环在中。用声明的变量对语句来说是局部的。

此表达式的结果将被丢弃。

条件 可选

在每次循环迭代之前要计算的表达式。如果此表达式计算为true,陈述执行。如果表达式计算为false,执行将退出循环并转到对于构造。

此条件测试是可选的。如果忽略,条件的计算结果始终为true。

事后思考 可选

在每次循环迭代结束时要计算的表达式。这发生在下一次评估之前条件。通常用于更新或增加计数器变量。

陈述

只要条件的计算结果为true就执行的语句。您可以使用块语句执行多条语句。要在循环中不执行语句,请使用空语句(;).

描述

与其他循环语句一样,您可以使用控制流程表里面陈述:

  • 打破停止陈述执行并转到循环后的第一条语句。
  • 持续停止陈述执行和重新评估事后思考然后条件.

示例

用于

以下内容对于语句以声明变量开始并将其初始化为0。它检查小于9,执行后面的两条语句,并递增每次通过循环后减少1。

js型
for(设i=0;i<9;i++){控制台.log(i);//更多语句}

初始化块语法

初始化块接受表达式和变量声明。但是,表达式不能使用在里面运算符未插入,因为它与用于。。。在里面循环。

js型
for(让i=“start”in window?windows.start:0;i<9;i++){控制台.log(i);}//SyntaxError:“for in”循环变量声明可能没有初始值设定项。
js型
//用圆括号括起整个初始值设定项for(让i=(window中的“start”?window.start:0);i<9;i++){控制台.log(i);}//用圆括号括“in”表达式for(让i=(窗口中的“start”)?窗口开始:0;i<9;i++){控制台.log(i);}

表达式可选

All three expressions in the head of the对于循环是可选的。例如,不需要使用初始化块初始化变量:

js型
设i=0;对于(;i<9;i++){控制台.log(i);//更多语句}

就像初始化条件部分也是可选的。如果省略此表达式,则必须确保中断正文中的循环,以避免创建无限循环。

js型
for(设i=0;;i++){控制台.log(i);如果(i>3)断裂;//更多语句}

您还可以省略所有三个表达式。同样,请确保使用打破语句结束循环并修改(增加)变量,以便break语句的条件在某些时候为true。

js型
设i=0;用于(;;){如果(i>3)断裂;控制台.log(i);i++;}

然而,如果您没有完全使用所有三个表达式位置,尤其是如果您没有使用第一个表达式声明变量,而是在上部范围中对某些内容进行了更改,那么可以考虑使用虽然相反,循环使意图更清楚。

js型
设i=0;而(i<=3){控制台.log(i);i++;}

初始化块中的词汇声明

在初始化块中声明变量与在上面声明变量有重要区别范围尤其是在创建关闭在循环体中。例如,对于以下代码:

js型
for(设i=0;i<3;i++){setTimeout(()=>{控制台.log(i);}, 1000);}

它记录了0,1、和2,如预期。但是,如果变量是在上部范围中定义的:

js型
设i=0;对于(;i<3;i++){setTimeout(()=>{控制台.log(i);}, 1000);}

它记录了,、和原因是每个设置超时创建一个新的闭包变量,但如果不是循环体的作用域,所有闭包在最终被调用时都会引用相同的变量,这是由于设置超时,它将在循环退出后发生,导致的值为在所有排队回调的正文中具有值.

如果使用变量语句作为初始化,因为变量用声明变量仅限于函数范围,但不包括词汇范围(即不能将其范围限定为循环体)。

js型
对于(var i=0;i<3;i++){setTimeout(()=>{控制台.log(i);}, 1000);}//日志3、3、3

初始化块的作用域效应可以理解为声明发生在循环体中,但恰好可以在条件事后思考部分。更准确地说,声明的大小写特殊对于循环-如果初始化是一个声明,然后每次计算循环体后,都会发生以下情况:

  1. 使用new创建新的词法范围-声明的变量。
  2. 上一次迭代的绑定值用于重新初始化新变量。
  3. 事后思考在新范围内进行评估。

因此,重新分配内部的新变量事后思考不会影响上一次迭代的绑定。

一个新的词法范围也在后面创建初始化,就在之前条件首次评估。可以通过创建闭包来观察这些细节,闭包允许在任何特定点保持绑定。例如,在此代码中,在初始化节未通过重新分配更新在中事后思考:

js型
for(设i=0,getI=()=>i;i<3;i++){console.log(getI());}//日志0,0,0

这不会记录“0,1,2”,就像如果得到我在循环体中声明。这是因为得到我不会在每次迭代时重新计算,而是创建一次函数并在变量,它指的是第一次初始化循环时声明的变量。价值的后续更新实际创建名为,其中得到我看不到。解决此问题的方法是重新计算得到我每一次更新:

js型
for(设i=0,getI=()=>i;i<3;i++,获取i=()=>i){console.log(getI());}//日志0、1、2

这个中的变量初始化变量,包括第一次迭代。所以,在这个例子中,得到我返回0,即使在迭代中,提前递增:

js型
for(设i=0,getI=()=>i;i<3;){i++;console.log(getI());}//日志0,0,0

事实上,您可以捕获变量并在稍后重新分配,则此更新的值对循环体不可见,循环体将看到下一个新的绑定.

js型
的(设i=0,getI=()=>i,incrementI=(,)=>i++;获取I()<3;增量I()) {控制台.log(i);}//日志0,0,0

此日志记录“0,0,0”,因为每个循环求值中的变量实际上是一个单独的变量,但得到我增量I读写最初的装订而不是后来宣布的。

用于无实体

以下内容对于循环计算中节点的偏移位置事后思考节,因此它不需要使用陈述节中使用分号。

js型
函数showOffsetPos(id){设left=0;设top=0;的(让itNode=document.getElementById(id);//初始化it节点;//条件left+=itNode.offset左侧,top+=itNode.offset顶部,itNode=itNode.offsetParent//事后想到); // 分号控制台日志(`“${id}”元素的偏移位置:左图:${左}像素;顶部:${top}像素;`,);}showOffsetPos(“内容”);//日志://“content”元素的偏移位置://左:0px;//顶部:153px;

请注意对于语句是强制性的,因为它代表空语句。否则对于语句获取以下内容控制台.log行作为其陈述部分,它使日志多次执行。

将for用于两个迭代变量

您可以使用逗号运算符.多个变量声明也可以用逗号连接。

js型
常数=[1,2,3,4,5,6];for(设l=0,r=arr.length-1;l<r;l++,r--){控制台.log(arr[l],arr[r]);}// 1 6// 2 5// 3 4

规格

规范
ECMAScript语言规范
#sec-for语句

浏览器兼容性

BCD表仅在浏览器中加载

另请参见