[英]Why doesn't this simple for loop work as expected?
One might expect the following to print out a
, b
, c
. 人们可能希望以下内容打印出
a
, b
, c
。
var i, rowName;
for (i = 0; i < 3; i++, rowName = ['a', 'b', 'c'][i]) {
console.log(rowName);
}
Instead, however, it prints out undefined
, b
, c
. 相反,它打印出
undefined
, b
, c
。 Why? 为什么?
To clarify: I know how to make this work; 澄清:我知道如何使这项工作; what I'm curious about is why the above doesn't work.
我很好奇的是为什么以上不起作用。
The reason it prints undefined
, b
, c
is because of how a for loop works. 它打印
undefined
, b
, c
的原因是因为for循环的工作方式。
for (initialization; condition; final expression)
Let's break down your for loop. 让我们分解你的循环。
initialization : i = 0
初始化 :
i = 0
condition : i < 3
条件 :
i < 3
final expression : i++, rowName = ['a', 'b', 'c'][i]
最终表达 :
i++, rowName = ['a', 'b', 'c'][i]
When your loop is first entered, i
is set to 0
. 首次输入循环时,
i
设置为0
。 This is the initialization step. 这是初始化步骤。 Then the condition step,
i < 3
, is checked. 然后检查条件步骤
i < 3
。 This is done before every iteration to decide whether or not to continue looping. 这在每次迭代之前完成,以决定是否继续循环。 After each loop, the final expression is evaluated.
在每个循环之后,评估最终表达式 。 In your example, you increment
i
before setting rowName
equal to an element in ['a', 'b', 'c']
based on the current index. 在您的示例中,在根据当前索引将
rowName
设置为['a', 'b', 'c']
的元素之前增加i
。
In your case, on the first iteration, rowName
is undefined
because the final expression is yet to be evaluated. 在您的情况下,在第一次迭代中,
rowName
undefined
因为尚未评估最终表达式 。 Every iteration thereafter behaves as you would expect since a final expression has already been previously evaluated. 之后的每次迭代都表现得如您所期望的那样,因为最终的表达式之前已经被评估过了。
If you want to do the tricky one-line for loop style, the "correct" syntax is: 如果你想做一个棘手的单行for循环风格,“正确”的语法是:
var array = ['a', 'b', 'c'];
for (var i = 0, rowName; rowName = array[ i++ ]; ) {
console.log(rowName);
}
Notice the ending ;
注意结局
;
of the for
loop declaration. for
循环声明。 There's technically an empty statement after the ;
从技术上讲,这是一个空洞的陈述
;
which is where you normally would do i++
. 这是你通常会做的
i++
。
In this case, the "condition" of the for loop is taking advantage of the Javascript assignment operator. 在这种情况下,for循环的“条件”利用了Javascript赋值运算符。 If you have some code like this:
如果你有这样的代码:
var a;
if( a = 1 ) { // Note this is assignment = not comparison ==
console.log('true');
}
It will log "true". 它将记录“真”。 Why?
为什么? Because inside of an expression,
a = 1
actually returns 1
. 因为在表达式内部,
a = 1
实际上返回1
。 And 1
is "truthy," meaning it evaluates to true in a boolean context like an if
statement. 1
是“truthy”,意味着它在布尔上下文中像if
语句一样求值为true。
The opposite is also true, if your value is falsey: 如果您的价值是假的,则情况正好相反:
var a;
if( a = 0 ) {
console.log('true');
}
It will not log, because a = 0
is returning 0 (as well as assigning 0 to a
). 它不会记录,因为
a = 0
返回0(以及将0赋值给a
)。 And 0 is falsey. 0是假的。
This whacky for-loop syntax is only for certain conditions: 这种糟糕的for循环语法仅适用于某些条件:
null
, undefined
, ""
, etc) it will prematurely terminate the loop, because of how operators work as mentioned above. null
, undefined
, ""
等),它将过早地终止循环,因为运算符如上所述工作。 i
. i
。 It will be off by 1 for every iteration of the loop, because i++
is executed before the for
block. i++
在for
块之前执行。 That is, the first time your for
body executes, i
will be 1, not its declared starting value of 0. for
身体第一次执行时, i
将是1,而不是它声明的起始值0。 I think you want this? 我想你想要这个?
var i, rowName;
for (i = 0; i < 3; i++){
rowName = ['a', 'b', 'c'][i];
console.log(rowName);
}
You are reassigning rowName
at each step of the loop and it's undefined
to begin with. 你在循环的每一步重新分配
rowName
,并且开始时它是undefined
。 Here's what you can do: 这是你可以做的:
for(var i=0,rowName=['a','b','c'],l=rowName.length; i<l; i++){
console.log(rowName[i]);
}
or something like: 或类似的东西:
var rowName = ['a', 'b', 'c'];
for(var i=0,l=rowName.length; i<l; i++){
console.log(rowName[i]);
}
The real issue is that the third condition inside for(assign; test; execute)
does not execute
until until one test
of the loop is satisfied. 真正的问题是,在满足循环的一个
test
之前for(assign; test; execute)
内部的第三个条件才会execute
。 If the test
fails execute
never happens. 如果
test
失败, execute
永远不会发生。 If the test
passes execute
really begins after the first pass of the loop. 如果
test
通过execute
确实在第一次循环后开始。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.