javascript的几种常见遍历数据结构的语法

接触JavaScript这么多年,第一次总结一下它的遍历语法。以前我大部分时间都在老版本的JavaScript下写代码,所以大部分时间都是用for...in,随着ES6的发布,有必要对各个遍历语法进行梳理,指出它的优缺点。

for/while循环语句

这就不多说了,所有语言都会涉及的循环。不过单纯的for/while能力有限,而且性能上也堪忧。而且你必须借助特定的结构才能遍历数据结构。这里就不详解了,简单举例:

var arr = [1,2,3];
for(var i = 0,len = arr.length;i < len;i ++) {
  var value = arr[i];
}

for...in语句

这也是JavaScript比较早特有的一个语句。它的作用是遍历对象的键名。

用法

var obj = {
  a : '1',
  b : '2',
  c : '3'
};
for(var key in obj) {
  var value = obj[key];
}

优点

它可以支持所有对象类型的数据,包括数组,甚至是函数等。而且语法简单,在其他语言中都很少看到。

缺点

不仅遍历普通键,连原型链上的键都去遍历了。

建议

在遍历常用对象时使用,这里的常用对象,就是我们上面举例的键值对(不是Map)。

forEach方法

在php中都有foreach语法,但是JavaScript中并没有,而且php中的foreach遍历对象也OK。但在JavaScript中,forEach仅是数组提供的内置方法。

用法

[1,2,3].forEach(function(value,index){
  console.log(index + ':' + value);
});

有点

可以同时获取index和value,不必再像以前遍历数组那样,还要再在for的{}去获取值。

缺点

仅支持数组。而且一旦调用,会完全遍历一次,break, continue, return都无效。

建议

仅在遍历数组的时候使用。

for...of语句

这是ES6新增的语法,它基于ES6新增的Iterator和Symbol开发的,也就是说我们用ES5代码只能模拟,但无法从原理上实现它。

用法

var list = new Map().set('a',1).set('b',2).set('c',3);
for (var [key,value] of list) {
  console.log(key + ' => ' + value);
}

优点

在遍历中直接取值。感觉上和for...in形成互补,一个在遍历中取键名,另一个取值。另一个优点是,它可以遍历任何部署了Iterator接口的数据结构,甚至是非JavaScript的数据类型,即自己定义的数据结构。

缺点

除了Map结构外,不能取到键名。不能用来遍历普通对象。

建议

在遍历时想要值的时候,可以使用,但不能用在普通对象上面。Map类型推荐使用。

递归(尾调用)

ES6中对函数尾调用进行了优化,而如果尾调用结构还是一个递归函数,那么更加节省性能,简直升天。

用法

function forEach(object,factory,_keyIndex = 0,_keys = object.keys()) {
 var key = _keys[_keyIndex];
 var value = object[key];
 if(typeof factory === 'function') factory(key,value);
 _keyIndex ++;
 return forEach(object,factory,_keyIndex,_keys);
}
var obj = {
  a : 1,
  b : 2,
  c : 3
};
forEach(obj,function(key,value){
  console.log(key + ' => ' + value);
});

优点

可以不涉及循环,递归的性能高于循环,特别是尾调递归。

缺点

代码结构复杂,千变万化,没有统一的规律可以掌握。

建议

当处理比较复杂的数据,可能用循环会消耗掉性能,而又比较在意性能的时候使用。

map、filter方法

map方法也可以遍历数组,但是它的主要用途是在遍历过程中进行修改,而filter遍历过程一样,但是只是通过回调函数的返回值来确定是不是要保留当前遍历到的这个值。也就是说,这两个方法都可能会修改被遍历的数组本身。

第三方each、map方法:理想方法

包括jQuery和underscore都提供了each。这是我们理想是使用方法,它结合了上面的forEach, for...of,是我们最希望得到的方法。

用法

$.each(object,(key,value) => {
  console.log(key + ' => ' + value);
});
[1,2,3].each((index,value) => {
  console.log(index + ':' + value);
});

有点

对我们最常用的array和object两种类型进行遍历都可以,同时可以得到键名和值。

缺点

性能上不确定,毕竟不是语言的原生,内部肯定经过加工处理。而且目前不知道是否对Map等结构支持。

建议

在复杂度比较高的情况下,希望代码简洁明确,同时也基于这些第三方库的情况下使用。其实性能上也不用太过担心,毕竟现在的电脑都很牛逼。

2016-10-26 | , , ,

已有3条评论
  1. […] 为了方便,还是先说一下for…of吧,它是ES6新的遍历方式(《javascript的几种常见遍历数据结构的语法》),目前来看,浏览器不支持,连babel也不支持,要安装babel的扩展才支持。 […]

  2. […] JavaScript中遍历我已经在《javascript的几种常见遍历数据结构的语法》中讲过了,但是数组有几个自带的遍历方法map、forEach、reduce、filter他们的区别是什么呢?本文简单的总结一下,让你装逼无误。 […]