在相当一段时间的情况下,我认为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
声明.如果有人可以提供一个相对彻底的解释来说明世界上这个伏都教正在做它做什么,那将是绝对美妙的.非常感谢提前.
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对象.
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; };
INITIALIZER可以声明和初始化多个变量.STOP CONDITION是一个单独的测试(这里只是"i"),INCREMENTER是每次在body之后执行的表达式(逗号运算符允许你有多个子表达式,所有这些都被执行).for循环的主体只是空语句";"
在我看来,你引用的代码是混淆的.有更清晰的方法来编写相同的功能.
但是,你的理解是非常正确的.以下是完全相同的代码,除了空格和注释.
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文件以实现更快的加载(这是自动代码压缩器可以做的那种转换).