JavaScript循环控制语句知识详解

目录

一、while循环

二、do-while循环

三、for循环

四、for-in循环

五、forEach循环

六、for-of循环


       循环语句是指在满足条件的情况下反复地执行某一个操作。循环控制语句主要包括while循环和for循环两种,这两种循环中,又分为不同的情况。

一、while循环

       while语句属既是循环语句,也是判断语句,实现循环操纵。通过判断条件是否满足来控制是否要重复执行内部代码。while语句的语法结构如下:

while(条件表达式语句){
    //循环代码块...
}

       while循环语句经常用于循环次数不确定的情况下

       while循环语句也被称为前测试循环语句。因为他要先判断循环条件是否成立,根据结果再决定是否进行重复执行操作。也就是说,while语句执行循环代码之前先判断条件表达式是否成立,如果为true,则执行内部代码,否则结束循环。

       注意:使用while语句时,一定要保证条件表达式存在false值,否则将形成一个死循环。

二、do-while循环

       do-while语句和while基本差不多,但有所不同的时,do-while先执行一次内部代码之后根据判断条件是否成立再决定是否继续执行还是结束循环。do-while语句的语法结构如下:

do{
    //循环代码块...
}while(条件表达式);

       do-while语句和while语句一样,经常用于循环次数不确定的情况下。不过do-while语句至少循环一次,然后判断表达式的结果再决定是否要继续循环。

       注意:和while循环不一样,do-while循环的结尾处,即括号后面有一个分号“;”表示while语句的结束,否则内部代码不但不会执行,程序还会陷入死循环。

三、for循环

       for语句也是一种前测试循环语句,但它具有在执行循环之前初始化条件、定义循环条件和每次循环后修改计数变量的方式。具体语法如下:

for(初始表达式 ; 条件表达式 ; 增量表达式){
    //循环代码块
}

       从语法格式中可以看到,for关键字后面的括号中,存在3个使用分号(;)分隔的表达式,这3个表达式的主要作用如下:

       * 初始表达式:用于声明for循环中使用的变量并赋初始值,该表达式只在循环开始时执行一次。

       * 条件表达式:用于指定for循环执行结束的条件。每次执行循环式都要先判断条件表达式是否满足,如果值为true,则执行循环,反则结束循环。

       * 增量表达式:用于修改包含在表达式中的循环变量的值。通过增加或减少循环变量的值,使循环趋向结束。该表达式在每次执行了循环体之后重复执行。

       所以,整个for循环执行的流程是:

  1. 执行初始表达式,给循环变量赋初始值。
  2. 判断条件表达式的值是否满足循环条件,结果为true,则执行循环代码块。
  3. 执行完循环代码块之后,接着执行增量表达式,改变循环变量的值。
  4. 重复执行(2)、(3)步,直到条件表达式的值为false时,退出循环。

       注意:和while循环、do-while循环一样,一定要保证循环条件存在false值,否则将形成一个死循环。

       上述语法是for循环的常规写法,除此之外还可以写成如下这种形式:

var numObj = [1, 2, 3];
for(var i = 0, num; num = numObj[i++];) {
	console.log(num)
}

       其实这种写法也是满足for循环的要求的,通过for循环的语法我们可以知道。循环的终止条件就是条件表达式为false。在JavaScript中0、null、undefile、false和空字符作为判断条件时,结果均为false。所以我们可以改写成这样

var numObj = [1, 2, 3];
for(var i = numObj.length; i--; ) {
	console.log(numObj[i])
}

       这种写法的原理就是,每次循环完毕之后都需要访问判断表达式,此时会执行i--表达式,当循环到i的值为0时返回false从而终止循环。

       让我们再回到上面的第一个案例代码。在循环初始阶段,定义了一个num变量用来存储每次循环结束之后,执行判断表达式时所存储numObj的元素值。从代码中我们可以知道循环变量i累加到一定程度之后一定会大于数组numObj的长度,此时访问的是空指针,所以会将undefined赋值给num之后判断结果为false从而结束循环。这种些话我们可以改写成正常的写法,代码如下:

for(var i = 0,num; i < numObj.length;) {
	num = numObj[i++]
	console.log(num)
}

四、for-in循环

       for-in语句是一种精确的迭代语句,专门用来枚举对象的属性或获取数组中的元素等。具体语法如下:

for(变量 in 对象){
    //循环代码块
}

       需要注意的是,如果迭代对象属性或者元素值为null或者undefined时,for-in语句会抛出错误。ECMAScipt5更正了这一行为,对于这种情况不再抛出错误,只是不执行循环体。为了保证最大兼容性,建议在使用for-in循环之前,先监测该对象的值是不是null或undefined。

       下面让我们来看一看for-in循环的具体例子:

//声明一个对象
var Person = {name:"Laoye",sex:"male",age:18}
//使用for-in遍历这个对象,i表示对象的属性
for(var i in Person) {
	console.log(Person[i])
}
//声明一个数组
var Array = [1,2,3,4]
//使用for-in遍历这个对象,i表示对象的索引
for(var i in Array) {
	console.log(Array[i])
}

       for-in语句不但可以枚举对象的属性还可以枚举数组的元素。但要知道的是,两者访问的方式并不相同。前者通过访问键值对中键获取其值,而后者通过索引来获取元素值。那么可以看出for-in循环中内部通过判断对象类型从而决定了变量存储的内容。值得注意的是,变量i的数据类型为字符串,只在迭代对象时,其值存储的是字符,而迭代数组时,其值存储的是数值字符。

       注意:ECMAScript对象的属性是没有顺序的。因此,通过for-in循环输出的属性名的顺序是不可预测的。具体来讲,所有属性都会被返回一次,但返回的先后次序可能会因浏览器而存在差异。

       介绍完for-in循环的概念之后,我们再来深入的探讨一下for-in循环中一些比较重要的问题。

       4.1 实例函数的prototype属性的调用错误问题

       需要注意的是,如果为循环对象的原型函数添加了prototype属性,在遍历时会将该属性给遍历出来,具体的代码和效果如下:

//为Object原型函数添加一个方法属性
Object.prototype.getName = function(){
	return "My name is " + this.name;
}
var Person = {name:"Laoye",sex:"male",age:18}
for(var i in Person){
	console.log(Person[i])
}

       控制台输出结果:

       之所处出现这种问题,是由于所有对象都继承了Object对象实例,因此在Object对象中定义的prototype属性均会被它所实例化的对象所继承并被访问。

       想要解决这种问题,我们可以在for-in循环中增加一个hasOwnProperty函数来判断对象自身(不包括原型链)是否具有通过prototype创建的指定名称的属性。例如将上面的代码改写成:

Object.prototype.getName = function(){
	return "My name is " + this.name;
}
var Person = {name:"Laoye",sex:"male",age:18}
for(var i in Person){
	if(!Person.hasOwnProperty(i)){
		continue;
	}
	console.log(Person[i])
}

五、forEach循环

       在ECMAScript5中引入了新的循环forEach循环。它是JavaScript的内置方法,用调用数组的每个元素,并将元素传递给回调函数。它的语法结构如下:

arrayObj.forEach(function(currentValue, index, arr){
    //执行的代码...
},thisValue);

       * function(currentValue, index, arr):必填项。表示数组中每个元素需要调用的函数。

       - currentValue:必填项,表示当前元素。

       - index:可选项,表示当前元素索引值。

       - arr:可选项,表示当前元素所属的数组对象。

       * thisValue:可选项。传递给函数的值一般用this,如果该值为空则会将undefined传递给this值。

       具体实例如下:

function numFunc(){
	this.count = 0;
	this.average = 0;
}
numFunc.prototype.Calculation = function(arry){
	arry.forEach(function(cont){
		this.count += cont;
	},this)
	this.average = this.count/arry.length;
	alert("和为:"+this.count+",平均数为:"+this.average);
}
var numObj = new numFunc();
numObj.Calculation([1,3,5,7,9]);

       如果给 forEach() 传递了 thisValue参数,当调用时,它将被传给 callback 函数,作为它的 this 值。否则,将会传入 undefined 作为它的 this 值。

       在这里我们要知道是:numObj对象调用Calculation函数,则其作用域内的this就是指当前调用函数,即numFunc函数。最重要的是count属性和average属性只有实例化对象才能访问。所以如果不在里面传入this值,可能会导致计算错误。

       注意:forEach 方法按升序为数组中含有效值的元素执行callback 函数,那些已删除或者未初始化的项将被跳过。更重要的是,在forEach循环过程中是无法终止(break)或者跳出(continue),除了抛出异常。所以如果需要提前终止循环或者跳过某一次循环,则不应该使用forEach循环。

六、for-of循环

       前面介绍了for-in循环和forEach循环函数。但是两者都存在一些致命缺点:

  1. for-in循环对数组遍历的索引并不是数值而是字符。在遍历对象属性时,无法确认属性的遍历顺序,如果数组中同时存在数值和字符的话那就更头疼了。
  2. for-in循环甚至原型链上的属性都被访问到。
  3. forEach循环无法终止或者跳过循环。

       ECMAScript6中又引入了一个新的循环,即for-of循环。它的格式与for-in循环一样,但是却弥补了for-in循环和forEach循环函数的缺点。它的语法如下:

for (variable of iterable) {
    //statements
}

       * variable:在每次迭代中,存储本次遍历元素或属性的值或对象。

       * iterable:被迭代枚举其属性或元素的对象。

       for-of循环到底有多强大呢?它到底可以做些什么?下面让我们来看一看,for-of循环到底有那些特点:

  1. 可以正确响应break、continue、return。
  2. 支持大多数数组对象,例如DOM NodeList对象。
  3. 支持字符串遍历,将字符串视为字符数组进行遍历。
  4. 同时还支持Map和Set对象遍历(ES6新增的类型)

       但要注意的是,for-of循环虽然很强大,但是却不支持普通对象。如果想要迭代普通对象的属性,可以通过Object.keys()函数获取对象的所有key数组,然后再遍历。亦或者使用for-in循环来迭代对象属性,但是要注意原型链上的属性。接下来,我看看具体的例子:

6.1 迭代Array对象

var list = [10, 20, 30];
for(var value of list) {
	console.log(value);
}

6.2 迭代String对象

var Str = "Hello Word";
for(var value of Str) {
	console.log(value);
}

6.3 迭代Map对象

var mapObj = new Map([
	["name", "LaoYe"],
	["sex", "male"],
	["age", "18"]
]);
//遍历Map对象
for(var mapList of mapObj)
console.log(mapList);
//获取键或值
for(var [keyName, keyValue] of mapObj)
console.log("key = "+keyName+" , value = "+keyValue);

6.4 迭代DOM集合

var list = document.getElementsByClassName("list")
//遍历Map对象
for(var domObj of list){
	console.log(domObj);
}

       除此之外还有很多,大家有兴趣的话可以去找找,这里就不一一列举了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值