慎重用for...in与for...of

for...infor...of都是用于数据的遍历。for...inES5标准,用于遍历对象属性(键),而for...ofES6标准,是对for...in的修正,用于遍历对象元素(值),for...of兼容性不是很好(除了PC端老顽固IE之外,移动端某些安卓机和浏览器也是不支持它,具体可以查看MDN)。

for…in

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Object.prototype.objMethod = function() {};
Array.prototype.arrMethod = function() {};

var arr = [2, 9, 5], obj = { name: '2ue', w: 130 };
arr.msg = 'hello';
obj.msg = 'hello';

for (var i in arr) {
console.log(i); // "0", "1", "2", "msg", "arrCustom", "objCustom"
}

for (var i in arr) {
if (arr.hasOwnProperty(i)) {
console.log(i); // "0", "1", "2", "msg"
}
}
for (var i in obj) {
console.log(i); // "name", "w", "msg", "objCustom"
}

for (var i in obj) {
if (obj.hasOwnProperty(i)) {
console.log(i); // "name", "w", "msg"
}
}

由上面的例子可以看出,for...in的一些特性:

  • 可以对JSON对象(数组和对象)进行遍历
  • for...in会遍历对象的所有可枚举属性,包括原型,例如一些我们挂载到原型链上的一些methodname
  • 遍历很有可能不是按照对象的内部顺序(我们预期的)进行
  • 对数组遍历时index索引为字符串型,在某些时候直接进行几何运算可能达不到预期结果

for…of

for...in貌似强大的同时也带来很多副作用,想要达到预期的记过需要额外的代码来处理,所以for...of应运而生

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Object.prototype.objMethod = function() {};
Array.prototype.arrMethod = function() {};

var arr = [2, 9, 5], obj = { name: '2ue', w: 130 };
arr.msg = 'hello';
obj.msg = 'hello';

for (var i of arr) {
console.log(i); // 2, 9, 5
}
//如果用for...of循环对象,会报错`obj is not iterable`
for (var i of obj) {
console.log(i);
}

可以看出,for...of方法在for...in上做了优化,并且限制了只能遍历数组。当然在ES5中,具有遍历数组功能的还有mapfiltersomeeveryreducereduceRight等,但是需要注意的是,有些方法不能被break句柄打断循环,使用retun也不能返回到外层,如forEach

其实不难看出for...in是属于鸡肋属性了,而for...of由于兼容性原因,在某些地方也应该慎用,即使是移动端也要慎用,应该它并不兼容所有内核。

参考

for…in
for…of
for-of循环是遍历实现iterator接口的成员