关于for...in和for...of的思考

时间:2022-03-13 09:49:38

关于for...in和for...of的思考

在编写js代码的时候,我们经常性的要对数据集合进行遍历,Array、Object、以及ES6新属性Map、Set,甚至String类型都是可遍历的

我们来看看,一般我们都用什么方法去遍历这些集合:

以Array遍历举例
  1. 比较笨的方法就是这样:
    for(var index=0;index<arr.length;index++){
    console.log(arr[index]);
    }
  2. 也可以用jqurey的$.each()方法:
    $.each(arr,function(index,value){
    console.log("索引"+index+"值"+value)
    });
  3. 还有就是ES5中的forEach方法
    arr.forEach(function (value) {
    console.log(value);
    });

    语法上简洁了一些,但是它有一个小小的不足:你不能用break语句跳出循环且不能在这个封闭的函数内使用return语句。
  4. 如果使用for...in呢
    for (var index in arr) {
    console.log(myArray[index]);
    }

    但是这个就会产生有几点问题:

    1、数组的索引值index是String类型的“0”,“1”,“2”等等,而不是Number类型。当你进行算术运算时(“2”+1==“21”)也许并不是你期望的结果,所以运算前需要类型转换,这很不方便。
    2、循环体不仅会遍历数组的元素,甚至连expando属性也遍历出来了。举个例子,如果你的myArray数组中有一个叫做name的属性,遍历时就将 index ==”name”也遍历出来,这样就多了一次执行。即时这些属性在数组的原型链上是可直接访问的(会访问到原型链上的属性)。
    var a = ['A', 'B', 'C'];
    a.name = 'Hello';
    for (var x in a) {
    alert(x); // '0', '1', '2', 'name'
    }

    3、最让人无语的是,在某些情况下,这段代码在遍历数组元素时顺序是任意的。

总而言之,for-in语法是被设计来遍历普通的“键值对”对象的,不适合用在数组上。

为了解决这个问题,ES6提出了for...of方法

代码如下:
var a = ['A', 'B', 'C'];
a.name = 'Hello';
for (var x of a) {
alert(x); // 'A', 'B', 'C'
}

第一眼看可能在构建上与for...in并无太大的区别,但是却有这几点好处:

这是目前遍历数组最简洁和直接的语法;
它避免了for-in的所有缺陷;
与forEach()不一样,它支持break,continue和return。

for-in循环用于遍历对象属性。

for-of循环用于遍历数据——比如数组中单值。

当然,for...of可不只是为遍历数组而设计的,基本上所有的类数组集合都适用(当然最好不要是对象)

'use strict'

var a = ['A', 'B', 'C'];
var s = new Set(a);
var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]);
a.name='123';
for (var x of a) { // 遍历Array
console.log(x);//A,B,C
}
for (var x of s) { // 遍历Set
console.log(x);//A,B,C
}
for (var x of m) { // 遍历Map
console.log(x[0] + '=' + x[1]);//1=x,2=y,3=z
}
for(var x of 'abc'){//遍历String
console.log(x);//a,b,c
}


总结,遍历类数组的集合可以用强大的for...of,对象还是乖乖的用for...in吧。

参考文章:
廖雪峰的官方网站--iterable
【探秘ES6】系列专栏(二):迭代器和for-of循环