迭代器和生成器-可迭代协议与for-of循环

99 阅读1分钟

可迭代协议

ES6规定,如果一个对象具有知名符号属性 Symbol.iterator ,并且属性值是一个迭代器创建函数,则该对象是可迭代的(iterable)。

// 该对象为可迭代对象
const obj = {
    [Symbol.iterator](){ // 迭代器创建函数
        return {
            next(){
                return {
                     value: 1,
                     done: false
                }
            }
        }
    }
}
  1. 思考:如何知晓一个对象是否是可迭代对象?
const divs = document.querySelectorAll('div');
const iterator = divs[Symbol.iterator]();
iterator.next();
  1. 思考:如何遍历一个可迭代对象?
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}
}

思路:

  1. 先得到对象所有的属性名 Object.keys()
  2. 定义下标
  3. 每次调用next方法,生成一个对象
  4. 判断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}
   ]
*/