普通对象for..of...遍历的实现
背景
ES6提供for...of...结构可直接遍历数组的每个元素,不需要循环计数器变量,但该结构不适用于普通对象,测试如下:
// 测试数组
var arr = [10,20,30]
for(var ele of arr){
console.log(ele);
}
// 依次输出 10 20 30
// 测试普通对象
var obj = {a:10,b:20,c:30}
for(var val of obj){
console.log(val)
}
// 报错:obj is not iterable(obj不可迭代)
原因分析
ES6中部份数据结构(如数组)能用for...of...遍历,是因为它们本身提供了Iterator接口,所谓Iterator接口需要部署在对象的Symbol.Iterator属性上,属性值需为实现了如下功能的函数(摘自阮一峰老师 《ECMAScript 6 入门》):
function makeIterator(array) {
var nextIndex = 0;
return {
next: function() {
return nextIndex < array.length ?
{value: array[nextIndex++]} :
{done: true};
}
};
}
解决方案
为普通对象设置如下Symbol.Iterator属性,且设置在Object.prototype上
Object.prototype[Symbol.iterator]=function(){
var that=this
var keys=Object.keys(that);
var index=0;
return {
next:function(){
return index<keys.length?{value:that[keys[index++]]}:{done:true}
}
}
}
// 再次测试
var obj = {a:10,b:20,c:30}
for(var val of obj){
console.log(val)
}
// 依次输出 10 20 30 成功实现用用for...of...结构遍历普通对象