所以我正在阅读关于改组阵列的内容。然后我遇到了this script:
shuffle = function(o){ //v1.0
for(var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
return o;
};
当我仔细观察时,for
甚至根本没有{}
!但它像魔术一样有效。我很想知道它是如何工作的。 (以及一堆逗号。)
答案 0 :(得分:10)
for ()
后面的内容可以是任何声明;可以是花括号的东西,也可以是单个表达式,也可以是空表达式。 for (...);
相当于for (...) {}
。当然,这应该只与一个自然终止的for循环一起使用,否则你手上会有无限循环。
逗号实际上是二级分号;它们主要用于单独的语句,但它们可以在for循环中工作(以及其他地方;这是对它们的非常草率的定义)。
for (
// initialisation: declare three variables
var j, x, i = o.length;
// The loop check: when it gets to ``!i``, it will exit the loop
i;
// the increment clause, made of several "sub-statements"
j = parseInt(Math.random() * i),
x = o[--i],
o[i] = o[j],
o[j] = x
)
; // The body of the loop is an empty statement
这可以用更可读的形式表示:
for (
// initialisation: declare three variables
var j, x, i = o.length;
// The loop check: when it gets to ``!i``, it will exit the loop
i;
// note the increment clause is empty
) {
j = parseInt(Math.random() * i);
x = o[--i];
o[i] = o[j];
o[j] = x;
}
作为while循环,可能是:
var j, x, i = o.length;
while (i) {
j = parseInt(Math.random() * i);
x = o[--i];
o[i] = o[j];
o[j] = x;
}
答案 1 :(得分:4)
对于我们不需要{}的单个语句,每个计算都在相同的语句中,但也在此语句中; (句子终止符最后使用)表示下一个语句不属于for语句。无论逻辑是什么,它都是相同的。
for(var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
for(var j, x, i = o.length;// Initialization
i;// Work until i is zero
j = parseInt(Math.random() * i),
x = o[--i], o[i] = o[j], o[j] = x);//Here he is computing his logic
答案 2 :(得分:2)
首先,我想指出这样的循环被认为是不好的风格,因为它非常难以理解并导致很多混乱。这是优化出错的典型例子。
查看specs,您会发现for(...)
必须后跟语句。
它可以是any statement,包括块。所以这些都是有效的:
for (...)
foo; // expression statement
,
for(...)
{
// block statement
}
,
for(...)
if(...) // If statement
foo;
,当然还有
for (...)
;
因为“;
”是empty statement。它什么都不做,但它足以使for(...);
在语法上有效。
现在,对于逗号。注意,parens的内容必须是三个expressions,(每个都是可选的),用分号分隔。几乎所有“一切”都符合表达式,包括comma-separated lists of expressions。虽然鲜为人知,但这些工作基本上都在JS中,不仅仅在for
循环中。它们只是一个接一个地进行评估。
所以,你的循环可以像这样重写
shuffle = function(o) {
var j, x, i = o.length;
while (i) { // for-loops are just while-loops in disguise
j = parseInt(Math.random() * i), // even better: replace , by ;
x = o[--i],
o[i] = o[j],
o[j] = x;
}
return o;
};
此外,x = o[--i]
应写为i--; x = o[i]
。
答案 3 :(得分:1)
如果全部在一行,则不需要括号。很多时候,在括号内的第三部分中,您只看到i++
或类似的东西。真的,你可以在那里做很多不同的事情。如果您能够在第三部分中打包所有内容,则甚至不需要for
循环的主体。
for (first section; second section; third section);
第一部分
声明并初始化变量。这些变量包含在循环的范围内。
第二部分
这是每次循环检查的条件。
第三部分
每次循环后运行的代码。它可以像递增一个变量一样简单,也可以像......一样复杂,只要语法正确就可以放在线上。
答案 4 :(得分:1)
看起来我没有正确读取循环。
在这种情况下,评估发生在for循环的条件中。
所以for循环有三个部分
for (initial variables; end cases; what to do every iteration)
你定义一些初始的东西并使用传递给函数的o
,定义一个结束案例,然后在每次迭代时计算一些东西。最后,o
有一个新值,然后返回。
答案 5 :(得分:0)
所有工作实际上都是在for
陈述的内容中完成的。循环没有明确的主体,所以最后的;
只是说主体是一个空语句。
,
(逗号)运算符从左到右计算表达式,并返回最右侧的值。
循环基本等同于:
for(var j, x, i = o.length; i > 0;)
{
j = parseInt(Math.random() * i--);
x = o[i];
o[i] = o[j];
o[j] = x
}