关于JavaScript for()循环伏都教

时间:2009-03-23 18:41:55

标签: javascript

我认为for循环可以 以下列格式存在,我已经有一段时间了:

for (INITIALIZER; STOP CONDITION; INC(DEC)REMENTER)
 {
    CODE
 }

但是,大多数绝对并非如此;看看Fisher-Yates Shuffle的这个JavaScript实现:

shuffle = function(o)
 {
    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循环声明中,这个世界是如何进行的?我的意思是......它甚至没有打开支架!所有的魔法都在for语句中就在那里完成。如果有人可以提供一个相对彻底的解释来说明世界上这个伏都教正在做它做什么,那将是绝对美妙的。非常感谢。

9 个答案:

答案 0 :(得分:14)

shuffle = function(o){
     for (
          var j,                // declare j
              x,                // declare x
              i = o.length;     // declare i and set to o.length
          i;                    // loop while i evaluates true
          j = parseInt(Math.random() * i), // j=random number up to i
            x = o[--i],         // decrement i, and look up this index of o
            o[i] =  o[j],       // copy the jth value into the ith position
            o[j] = x            // complete the swap by putting the old o[i] into jth position
          );
     return o;
     };

这是从i开始等于位置的数量,并且每次交换卡片i和j,其中j是每次最多i的随机数,根据算法。

如果没有令人困惑的逗号集,可以更简单地编写,真实。

顺便说一句,这是这是javascript中唯一的for循环。还有:

 for(var key in arr) {
      value = arr[key]);
 }

但要小心,因为这也会遍历对象的属性,包括传入一个Array对象。

答案 1 :(得分:11)

for循环的通用格式(不是for-in循环)是

for ( EXPRESSION_1 ; EXPRESSION_2 ; EXPRESSION_3 ) STATEMENT

第一个EXPRESSION_1 通常用于初始化循环变量,EXPRESSION_2是循环条件,而EXPRESSION_3 通常是递增或递减操作,但没有规则那说他们必须表现得那样。它等同于以下while循环:

EXPRESSION_1;
while (EXPRESSION_2) {
    STATEMENT
    EXPRESSION_3;
}

逗号只是一个操作符,它将两个表达式组合成一个表达式,其值是第二个子表达式。它们用于for循环,因为每个部分(以分号分隔)需要是单个表达式,而不是多个语句。没有理由(除了可能在文件中保存一些空间)来写这样的for循环,因为这是等价的:

shuffle = function(o) {
    var j, x;
    for (var i = o.length; i > 0; i--) {
        j = parseInt(Math.random() * i);
        x = o[i - 1];
        o[i - 1] = o[j];
        o[j] = x;
    }
    return o;
};

答案 2 :(得分:8)

INITIALIZER可以声明并初始化多个变量。 STOP CONDITION是一个单独的测试(这里只是“i”),INCREMENTER是每次在body之后执行的表达式(逗号运算符允许你有多个子表达式,所有这些都被执行)。 for循环的主体只是空语句“;”

答案 3 :(得分:7)

我引用的代码在我看来是混淆的。有更清晰的方法来编写相同的功能。

然而,你的理解是非常正确的。以下是完全相同的代码,除了空格和注释。

for (
     // Initializer
     var j, x, i = o.length;
     // Continue condition
     i;
     // Operation to be carried out on each loop
     j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x
 )
 // empty body, equivalent to { }
 ;

写下等效文字要清楚得多:

var j,x,i = o.length;
while(i) {
    j = parseInt(Math.random() * i);
    x = o[--i];
    o[i] = o[j];
    o[j] = x;
}

为了便于阅读,还可以进行其他优化 - 包括使用while(i > 0)代替while(i),并在单独的行中将--i拆分为i--

除了可读性之外,没有理由让()存在。这两个是等价的:

{ // this block is to scope int i
   int i=0;
   while(i<100) {
       myfunc(i);
       i++;
   }
}

for(int i=0; i<100; i++) {
    myfunc(i);
}

您应该使用在给定时间内最易读的。我认为你的代码的作者做了相反的事情。公平地说,他可能已经这样做了,以便实现更小的JS文件以实现更快的加载(这是自动代码压缩器可以做的那种转换)。

答案 4 :(得分:4)

for循环的语法是:

for (pre-block; condition; post-loop-block)
    loop-block;

首先,执行预阻塞,定义各种变量。

在每个循环中:

  1. 检查条件
  2. 执行loop-block
  3. 执行post-loop-block
  4. 从1开始重复。

答案 5 :(得分:1)

他们几乎只是将循环体移动到增量部分。您可以将for循环重新编写为while循环,以了解它正在做什么:

 shuffle=function(o) {
    var j; //Random position from 0 up to the current position - 1
    var x; //temp holder for swapping positions
    var i=o.length; //current position
    while(i>0) { // Loop through the array
        j = parseInt(Math.random()*i); //get a lower position
        x = o[--i]; // decrement the position and store that position's value in the temp var
        o[i]=o[j]; // copy position j to position i
        o[j]=x; // copy the temp value that stored the old value at position i into position j
    }
    return o;
}

前三个var是扩展的initialzier,while中的check是停止条件,while的主体是for的增量部分所做的。

编辑:根据Gumbo的评论更正

答案 6 :(得分:1)

该陈述符合您的初始格式。

事实证明,你可以使用“,”(逗号)

添加多个句子

所以:

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,                           //INITIALIZER(s)
         x,
         i = o.length;

     i;                               // STOP CONDITION ( i ) 

     j = parseInt(Math.random() * i), // INC(DEC)REMENTER
     x = o[--i],
     o[i] = o[j],
     o[j] = x);  // CODE ( ; ) 

如您所见,它完全符合您的初始格式。

答案 7 :(得分:1)

这一直回到C语法 - javascript从中偷走了一堆。主要技巧是逗号运算符,除了循环外几乎没有出现在其他地方

答案 8 :(得分:0)

第一个子句初始化您要使用的任何变量。第二个条款确实是停止条件。第三个子句包括在每次迭代结束时要执行的任何逻辑。多个语句可以用逗号分隔。