JavaScript中几种遍历方法浅析

JavaScript中几种遍历方法浅析

前端入门菜鸟,对于平常用的几种遍历方法的掌握有点模糊,空闲之余总结一下遍历方法,将几种遍历方法进行区分并掌握。

1. for循环

  • 可以中断循环
  • 原数据会被改变
  • 对象和数组都使用,伪数组(集合)也适用
for(var i = 0; i < array.length; i++){
	//return;   // 函数执行被终止
	//break;    // 循环被终止
	continue; // 循环被跳过
} 
关于for循环,有以下几点需要注意
  • for循环中的 i 在循环结束之后任然存在与作用域中,为了避免影响作用域中的其他变量,可使用函数自执行的方式(匿名函数)将其隔离起来;
  • 尽量避免 for( var i = 0; i < array.length; i++) 的方式,这样的数组长度每次都被计算,效率低于上面的方式。可以使用for(var i = 0, len = array.length ; i < len; i++) 的方式,提高代码的利用率

2. for…in 遍历

适用于数组和对象(大部分情况下用来遍历对象)

  • 遍历数组时,i 代表索引值
  • 遍历对象时,i 代表 key 值,(遍历不到Symbol类型属性)
  • 也可遍历集合(基本不用),i 代表索引值
var array = [1, 2, 3, 4]
for(var i in array){
	console.log(i)
}
注意点:
  • 遍历数组时,i 值的类型为String类型,不是Number类型,使用此方法进行数组元素计算时,需要转换类型
  • 如果在数组原型对象上有方法,此时for…in方法不适用,比如:
Array.prototype.show = function(value){//函数已被简化
	return right;
}
 
var array = [1, 2, 3, 4];
for(var i in array){
	console.log(array[i]);
}

这段代码就是在上边的代码的基础上,为Array做了一下扩充。很简单,只是添加了一个用于搜索的函数(这个函数已被我简化成和上边那样)。但是我们来看运行会出现什么情况:

1
2
3
4
f (value){//函数已被简化
   return right;
} 

输出的结果中,多出了一行,这一行是一个函数,不是我们定义在数组中的值。到此这个问题就出来了, 对于使用for…in可能出现的错误,有两种方式可避免:

  1. 不使用for…in,老老实实使用普通for循环形式。
  2. 在for-in循环中增加一个hasOwnProperty的判断,如下:
Array.prototype.show = function(value){//函数已被简化
   return right;
}

var array = [1, 2, 3, 4];
for(var i in array){
  if(!array.hasOwnProperty(i)){
    continue
  }
  console.log(array[i]);
}

控制台输出结果为:

1
2
3
4
总之,for-in是被设计来遍历普通的“键值对”对象的,不适用于数组上

3. forEach 遍历

  • 只能用来遍历数组,其他类型(对象,集合)均不可以
  • 代码执行效率比for循环快
  • 不改变原数组
  • 遍历不能停止,即不能使用break,continue跳出循环,或者使用return结束
var arr=[9, 8, 7, 6, 5, 4]
arr.forEach(function(item,index,arr){
	console.log(value);//9 8 7 6 5 4
})
参数描述
item必选,当前循环元素
index可选,当前元素索引
arr可选,当前元素所属的数组对象

4. for…of 遍历

  • 可遍历数组和类数组
  • 不可遍历对象
  • 可以使用break,continue和return
  • 遍历循环的是数组中的每一项元素
var arr = ['kobe','james','durant','curry'];
arr.name = "数组";
 
for(var key in arr){
    console.log(key +': ' + arr[key]);	
}
console.log('-----------分割线-----------');
for(var item of arr){	
    console.log(item);
}

输出结果为:
在这里插入图片描述
上图对于for…in 和 for…each作了简单的对比, 对于数组中新添加的name属性, for…in遍历了出来,而for…of不会遍历出来,算是使用过程中需要注意的一个点吧

另: ES6 为字符串添加了遍历器接口,使得字符串可以被for…of循环遍历

for (let codePoint of 'foo') {
  console.log(codePoint)
}
// "f"
// "o"
// "o"

5. 明显减少代码量的一些高级遍历方法如下所示:

reduce()reduceRight()filter()map()every()some()

5.1 reduce() 和 reduceRight()
语法:
arr.reduce(callback,[initialValue])

callback (执行数组中每个值的函数,包含四个参数)

    1、previousValue (必选,上一次调用回调返回的值,或者是提供的初始值(initialValue))
    2、currentValue (虚悬,数组中当前被处理的元素)
    3、index (可选,当前元素在数组中的索引)
    4、array (可选,调用 reduce 的数组)

initialValue (作为第一次调用 callback 的第一个参数。)

注意: 如果没有提供initialValue,reduce 会从索引1的地方开始执行 callback 方法,跳过第一个索引。如果提供initialValue,从索引0开始。

var arr = [1, 2, 3, 4];
var sum = arr.reduce(function(prev, cur, index, arr) {
    console.log(prev, cur, index);
    return prev + cur;
})
console.log(arr, sum);

打印结果:
在这里插入图片描述
reduce是从左到右处理(从第一个成员到最后一个成员),reduceRight则是从右到左(从最后一个成员到第一个成员)

5.2 map() 和 filter()

map() 和 filter()两种方法的语法极为相似,语法结构均为

array.map(callback, [thisObject]);
array.filter(callback, [thisObject]);

callback接收三个参数
	1. item (必选, 当前元素的值)
	2. index (可选,当前元素的索引值)
	3. arr  (可选,当前元素属于的数组对象)

thisObject (可选。对象作为该执行回调时使用,传递给函数,用作 "this" 的值。
			如果省略了thisValue,或者传入 null、undefined,那么回调函数的 this 为
			全局对象)

filter方法用于过滤数组成员,满足条件的成员组成一个新数组返回。它的参数是一个函数,所有数组成员依次执行该函数,返回结果为true的成员组成一个新数组返回。该方法不会改变原数组

map方法将数组的所有成员依次传入参数函数,然后把每一次的执行结果组成一个新数组返回,不会改变原数组

[1, 2, 3].map(function(item, index, arr) { 
    return item * index; 
}); 
// [0, 2, 6]
[1, 2, 3, 4, 5].filter(function (item, index, arr) { 
    return index % 2 === 0; 
}); // [1, 3, 5]

注意点:map(),foreach(),filter()循环的共同之处:

1. foreach,map,filter循环中途是无法停止的,总是会将所有成员遍历完。
2. 他们都可以接受第二个参数,用来绑定回调函数内部的this变量,将回调函数内部的this对象,指向第二个参数,间接操作这个参数(一般是数组)

不同之处:
     forEach循环没有返回值;map,filter循环有返回值

5.3 some() 和 every()

这两种一般用来循环遍历,统计数组是否满足某个条件

  1. 遍历数组;
  2. 三个参数分别是item,index,arr(当前元素,索引,数组本身);
  3. 返回的都是布尔值

它们接受一个函数作为参数,所有数组成员依次执行该函数。该函数接受三个参数:当前成员、当前位置和整个数组,然后返回一个布尔值。

some方法是只要一个成员的返回值是true,则整个some方法的返回值就是true,否则返回false

var arr = [1, 2, 3, 4, 5];
arr.some(function (elem, index, arr) {
  return elem >= 3;
});
// true

而every方法则相反,所有成员的返回值都是true,整个every方法才返回true,否则返回false。两相比较,some()只要有一个是true,便返回true;而every()只要有一个是false,便返回false.

var arr = [1, 2, 3, 4, 5];
arr.every(function (elem, index, arr) {
  return elem >= 3;
});
// false

总结: some()只要有一个是true,便返回true;而every()只要有一个是false,便返回false.
这两种方法在实际开发时,实用性很强,比如一些复选框之类的操作,大大减少代码量

6. Object.key() 和 Object.getOwnPropertyNames()

Object.keys() 方法的参数是一个对象,返回一个数组。该数组的成员都是该对象自身的(而不是继承的)所有属性名,且只返回可枚举的属性。

var obj = {
  p1: 123,
  p2: 456
};
 
Object.keys(obj) // ["p1", "p2"]

Object.getOwnPropertyNames() 方法与Object.keys() 类似,也是接受一个对象作为参数,返回一个数组,包含了该对象自身的所有属性名。但它能返回不可枚举的属性。

var a = ['Hello', 'World'];

Object.keys(a) // ["0", "1"]
Object.getOwnPropertyNames(a) // ["0", "1", "length"]

上面代码中,数组的length属性是不可枚举的属性,所以只出现在Object.getOwnPropertyNames方法的返回结果中。

由于 JavaScript 没有提供计算对象属性个数的方法,所以可以用这两个方法代替。

var obj = {
  p1: 123,
  p2: 456
};
 
Object.keys(obj).length // 2
Object.getOwnPropertyNames(obj).length // 2
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值