对象的遍历
for...in循环可以用来遍历对象的可枚举属性列表,但是如果遍历对象的值呢?
以数组为例,我们最基础的方式就是for循环:
var myArray = [1, 2, 3];
for (var i = 0; i < myArray.length; i++) {
console.log(myArray[i]);
}
// 1 2 3
事实上这种并不是真的遍历值,而是在遍历下标来获取到对应的值。
ES5新增了一些数组的遍历方法,比如:forEach(..)、every(..) 和 some(..);每种方法都可以接受一个回调函数并将其应用到数组每个元素上,,唯一的区别就是它们对于回调函数返回值的处理方式不同。
数组也可以使用for..in,不过得到的也是数组下标,在ES6的时候,新增了for...of的循环方法,用于遍历数组的值。
var myArray = [1, 2, 3];
for (var v of myArray) {
console.log(v);
}
// 1
// 2
// 3
for..of 循环首先会向被访问对象请求一个迭代器对象,然后通过调用迭代器对象的next() 方法来遍历所有返回值。
而数组内置了@@iterator迭代器,所以for...of可以直接应用在数组上。
我们可以手动调用迭代器来实现遍历数组:
var myArray = [1, 2, 3];
var it = myArray[Symbol.iterator]()
it.next(); // { value:1, done:false }
it.next(); // { value:2, done:false }
it.next(); // { value:3, done:false }
it.next(); // { done:true }
如你所见,调用迭代器的 next() 方法会返回形式为 { value: .. , done: .. } 的值,value 是当前的遍历值,done 是一个布尔值,表示是否还有可以遍历的值。
注意,和值“3”一起返回的是 done:false,乍一看好像很奇怪,你必须再调用一次next() 才能得到 done:true,从而确定完成遍历。这个机制和 ES6 中发生器函数的语义相关,不过已经超出了我们的讨论范围。
和数组不同,普通的对象是没有内置迭代器的,所以它无法直接通过for...of来实现遍历值。
但是我们可以自己手动添加一个迭代器来实现:
var myObject = {
a: 2,
b: 3
};
Object.defineProperty(myObject, Symbol.iterator, {
enumerable: false,
writable: false,
configurable: true,
value: function() {
var o = this;
var idx = 0;
var ks = Object.keys(o);
return {
next: function() {
return {
value: o[ks[idx++]],
done: (idx > ks.length)
};
}
};
}
});
// 手动遍历 myObject
var it = myObject[Symbol.iterator]();
it.next(); // { value:2, done:false }
it.next(); // { value:3, done:false }
it.next(); // { value:undefined, done:true }
// 用 for..of 遍历 myObject
for (var v of myObject) {
console.log(v);
}
// 2
// 3
分类:
你不知道的JavaScript
标签:
for...of对象的遍历迭代器
版权申明
本文系作者 @木灵鱼儿 原创发布在木灵鱼儿站点。未经许可,禁止转载。
暂无评论数据