可迭代对象可通过 for...of进行循环。
迭代器的模拟
模拟迭代器:
function makeIterator(arr) {
var nextIndex = 0;
return {
next: function () {
return nextIndex < arr.length ? {
done: false,
value: arr[nextIndex++]
} : {
done: true
};
}
}
}
var it = makeIterator(['a', 'b', 1, 6, NaN, null, undefined]);
var res;
do {
res = it.next();
console.info(res.value);
} while (!res.done);
为了实现可迭代,一个对象必须实现 iterator 方法,这意味着这个对象(或其原型链中的一个对象)必须具有带 Symbol.iterator 键的属性
检测可迭代对象
判断当前对象是否为可迭代对象,检测该对象是否具备 Symbol.iterator 属性。
// 以数组为例
Array.prototype.hasOwnProperty(Symbol.iterator); // => true
可通过检测当前对象是否具有Symbol.iterator属性来判断当前对象是否为可迭代对象。Symbol.iterator 是一个函数,所以通过typeof来检测返回值,如果返回值为'function'则为可迭代对象,如果返回值为'undefined'则为不可迭代对象。
typeof [][Symbol.iterator]; // => 'function'
typeof {}[Symbol.iterator]; // => 'undefined'
typeof new Set()[Symbol.iterator]; // => 'function'
typeof new Map()[Symbol.iterator]; // => 'function'
typeof ''[Symbol.iterator]; // => 'function'
var list = document.querySelectorAll('p'); // 获取dom节点
typeof list[Symbol.iterator]; // => 'function'
typeof new Int8Array()[Symbol.iterator] // => 'function'
(function(){
typeof arguments[Symbol.iterator]; // => 'function'
})();
原生可迭代对象
原生具备 Iterator 接口的数据结构如下。
- Array
- Map
- Set
- String
- TypedArray
- 函数的 arguments 对象
- NodeList 对象
Symbol.iterator 为每一个对象定义了默认的迭代器,迭代器是一个对象,它提供了一个next()方法,用来返回序列中的下一项。数组如何使用.next() 方法:
var arr = [1,2,3];
var si = arr[Symbol.iterator]();
si.next(); //=> {value: 1, done: false}
si.next(); //=> {value: 2, done: false}
si.next(); //=> {value: 3, done: false}
si.next(); //=> {value: undefined, done: true}
可迭代对象的实现
如何实现一个自定义的可迭代对象:
var myIterator = {};
myIterator[Symbol.iterator] = function* () {
yield 'Bryan';
yield 'programmer';
yield 'bachelordom';
}
for (let val of myIterator) {
console.info(val);
}
// Bryan
// programmer
// bachelordom
var myIterator = {
name: 'Bryan',
job: 'programmer',
condition:'bachelordom',
*[Symbol.iterator](){
const self = this;
const keys = Object.keys(self);
for(let i=0,l=keys.length;i<l;i++){
yield self[keys[i]];
}
}
};
for (let val of myIterator) {
console.info(val);
}
// Bryan
// programmer
// bachelordom
总结
可迭代对象的特点:
- 可使用
for...of进行循环; - 对象或者原型链当中具有
Symbol.interator属性; - 可通过迭代器访问并跟踪该序列中的当前位置。(迭代器提供next()方法,返回对象包含done和value方法)
参考资料 《ECMAScript 6 入门》Iterator 和 for...of 循环 《MDN》迭代器和生成器 《MDN》Symbol.iterator