没有任何{}的for循环

时间:2012-06-13 03:59:00

标签: javascript

所以我正在阅读关于改组阵列的内容。然后我遇到了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甚至根本没有{}!但它像魔术一样有效。我很想知道它是如何工作的。 (以及一堆逗号。)

6 个答案:

答案 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
}