可迭代协议
ES6规定,如果一个对象具有知名符号属性
Symbol.iterator,并且属性值是一个迭代器创建函数,则该对象是可迭代的(iterable)。
// 该对象为可迭代对象
const obj = {
[Symbol.iterator](){ // 迭代器创建函数
return {
next(){
return {
value: 1,
done: false
}
}
}
}
}
- 思考:如何知晓一个对象是否是可迭代对象?
const divs = document.querySelectorAll('div');
const iterator = divs[Symbol.iterator]();
iterator.next();
- 思考:如何遍历一个可迭代对象?
const arr = [1, 3, 4, 2, 5];
const iterator = arr[Symbol.iterator]();
let result = iterator.next();
while (!result.done) {
const item = result.value;
console.log(item);
// 下一次迭代
result = iterator.next();
}
for-of 循环
for of循环用于遍历可迭代对象。
格式如下:
for(const item of iterator){
}
这是语法糖,等效于上面的代码。
const arr = [1, 3, 4, 2, 5];
for(const item of arr){
console.log(item); // 1 3 4 2 5
}
举例:如何修改以下代码,得到{propName: 'a',propValue: 1}
const obj = {
a: 1,
b: 2,
[Symbol.iterator]() {
return {
next() {
return {
value: 1,
done: false
}
}
}
}
}
for (const item of obj) {
console.log(item); // {propName: 'a',propValue: 1}
}
思路:
- 先得到对象所有的属性名
Object.keys() - 定义下标
- 每次调用next方法,生成一个对象
- 判断i是否超出下标,超出为false,不超出为true
完整代码如下:
const obj = {
a: 1,
b: 2,
[Symbol.iterator]() {
const keys = Object.keys(this); // ['a','b']
let i = 0;
return {
next: () => {
const propName = keys[i];
const propValue = this[propName];
const result = {
value: { propName, propValue },
done: i >= keys.length
}
i++;
return result;
}
}
}
}
for (const item of obj) {
console.log(item);
// {propName: 'a',propValue: 1}
// {propName: 'b',propValue: 2}
}
展开运算符与可迭代对象
展开运算符可以作用于可迭代对象,这样,就可以轻松的将可迭代对象转换为数组。
const arr = [...obj];
console.log(arr)
/* [
{propName: 'a',propValue: 1},
{propName: 'b',propValue: 2}
]
*/