5.5 循环
条件语句可以当成一条条分支路径,循环语句就是程序路径的回路,可以让一部分代码重复执行。
JavaScript有四种循环语句:while、do/while、for和for/in
5.5.1 while
while语句是一个基本的循环语句,语法如下:
while(expression) statement
在执行while语句之前,JavaScript解释器首先计算express的值,如果它的值是假值,那么程序将跳过循环体中的逻辑statement转而执行程序中的下一条语句。如果表达式expression是真值,JavaScript解释器将执行循环体内的逻辑,然后再次计算表达式expression的值,这种循环会一直继续下去,直到expression的值为假值为止。while(true)将会创建一个死循环。
|
5.5.2 do/while
do/while循环和while循环非常类似,只不过它是在循环的尾部而不是顶部检测循环表达式,这就意味着循环体至少会执行一次,do/while循环的语法如下:
do
statement
while(expression);
do/while循环和while循环语法上有两点不同之处, 首先,do/while循环必须使用关键字do来标识循环的开始,用while来标识循环的结尾并进入循环条件判断;其次,和while循环不同,do循环是用分号结尾,如果while的循环体使用花括号括起来,则while循环不使用分号结尾。
|
5.5.3 for
for语句对常用的循环模式做了一些简化。大部分的循环都具有特定的计数器变量。在循环开始之前要初始化这个变量,然后再每次循环执行之前都检测一下它的值。最后计数器变量做自增操作,否则就在循环结束后、下一次判断循环条件前做修改。在这一类循环中,计数器的三个关键操作是初始化、检测和更新。for语句就将这三步操作明确声明为循环语法的一部分,各自使用一个表达式来表示。for语句的语法如下:
for(initialize;test;increment)
statement
initialize、test和increment三个表达式之间用分号分隔,他们分别负责初始化操作、循环条件判断和计数器变量的更新。
等价的while循环
initialize;
while(test){
statement
increment;
}
JavaScript同样允许初始化表达式中带有var变量声明语句,这样的话就可以同时声明并初始化一个变量。每次循环执行之前都会执行test表达式,并判断表达式的结果来决定是否执行循环体,如果test计算结果是真值,则执行循环体中的statement,最后,执行increment 表达式。
*注意,for循环的表达式中三个表达式的任何一个都可以忽略,但是两个分号必不可少。
|
5.5.4 for/in
for/in语句也使用了for关键字,但它和常规的for循环完全不同的一类循环。for/in循环语句的语法如下:
for(variable in object)
statement
variable通常是一个变量名,也可以是一个产生左值的表达式或者一个通过var语句声明的变量,总之必须是一个适用于赋值表达是左侧的值。object是一个表达式,这个表达式的计算结果是一个对象,同样statement是一个语句或者语句块,它构成了循环的主体。
for循环可以很方便的遍历数组元素,for/in用来遍历对象属性成员更方便:
var a = [1,2,3]
for(var i = 0; i < a.length ; i++)
console.log(a[i]);
for(var p in a)
console.log(a[p]);
在执行for/in语句的过程中,JavaScript解释器首先计算object表达式。如果表达式为null或者undefined,JavaScript解释器将会跳过循环并执行后续代码。如果表达式等于原始值,这个原始值将会转换为与之对应的包装对象。JavaScript会依次枚举对象的属性来执行循环。在每次循环之前,JavaScript都会先计算variable表达式的值,并将属性名赋值给它。
只要for/in循环中variable的值可以当做赋值表达式的左值,它可以时候任意表达式。每次循环都会计算这个表达式,也就是说每次循环它计算的值有可能不同。
var o = {x:1 ,y:2 ,z:3};
var a= [],i = 0;
for(a[i++] in o);
console.log(a.length); //把所有对象属性复制到一个数组
JavaScript数组不过是一种特殊的对象,因此,for/in循环可以像枚举对象属性一样枚举数组索引。
for/in循环并不会遍历对象的所有属性,只有“可枚举”的属性才会遍历到。由JavaScript语言核心所定义的内置方法就不是“可枚举的”。比如,所有对象的都有toString(),但for/in循环并不枚举toString这个方法,除了内置方法外,还有很多内置对象的属性也是“不可枚举的”。而代码中定义的所有属性和方法都是可枚举的,对象可以继承其他对象的属性,那些继承的自定义属性也可以使用for/in枚举出来。
如果for/in的循环体删除了还未枚举的属性,那么这个属性将不会再枚举,如果定义了对象的新属性,这些属性通常也不会枚举到。
属性枚举的顺序
ECMAScript规范并没有指定for/in循环按照何种顺序类枚举对象属性。实际上,主流浏览器厂商的JavaScript实现是按照属性定义的先后顺序来枚举简单对象的属性,先定义的属性先枚举。如果使用对象直接量的形式创建对象,则将按照直接量中属性的出现顺序枚举。
在下列情况下,枚举的顺序取决于具体的实现:
除了所有非继承的“自有”属性以外的继承属性往往都是可枚举的,而且可以按照他们定义的属性进行枚举。如果对象属性继承原型,也就是他的原型链上有多个对象,那么链上面的每一个原型对象的属性的遍历也是依照特定顺序执行。
JavaScript的一些(但不是全部)实现依照数字顺序来枚举数组属性,而不是某种特定的顺序。但当数组元素的索引是非数字或数组是稀疏数组(数组索引是不连续的)时它们则按照特定顺序枚举。
|