Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

迭代协议(Iteration protocols) #196

Open
yaofly2012 opened this issue Nov 12, 2020 · 0 comments
Open

迭代协议(Iteration protocols) #196

yaofly2012 opened this issue Nov 12, 2020 · 0 comments

Comments

@yaofly2012
Copy link
Owner

yaofly2012 commented Nov 12, 2020

一、Iteration protocols

JS里可以通过for-in遍历对象,for遍历字符串和数组,并且数组还有独立的各种遍历方法。ES2015里又增加了一些数据集合(Set/Map/生成器函数)。为了对这些数据集合提供统一遍历方式引入了迭代协议。

迭代协议由两部分构成:

  1. 可迭代协议(iterable protocol)
  2. 迭代器协议(iterator protocol)

二、可迭代协议(iterable protocol) & 可迭代对象

2.1 可迭代协议(iterable protocol)

The iterable protocol allows JavaScript objects to define or customize their iteration behavior。

协议内容:

  1. 对象本身(或者原型链上)具有Symbol.iterator成员方法;
  2. Symbol.iterator成员方法返回值是个迭代器

通过名字也能看出Symbol.iterator成员方法就是为了获取可迭代对象的迭代器的。

2.2 可迭代对象

实现了可迭代协议的对象叫可迭代对象

2.3 可迭代对象的语法支持

1. for-of遍历

for (let value of ['a', 'b', 'c']) {
    console.log(value);
}

2. 展开语法...

console.log([...'abc']);   // ["a", "b", "c"]

3. yield*遍历

var gen = function* () {
    yield 1;
    yield* [12, 123];
    return 3;
}

4. 解构赋值

var gen = function* () {
    yield 1;
    yield* [12, 123];
    return 3;
}

var g = gen();
var [a, b, c] = g;

console.log(a, b, c); // 1 12 123

三、迭代器协议(iterator protocol)& 迭代器(iterator )

迭代器协议定义如何产生一系列值的标准方式(就像Promise/A+规范定义Promise对象)。
实现迭代器协议的对象叫迭代器

3.1 协议内容

  1. 具有next成员方法;
  2. next成员方法返回非null的对象,并且对象至少具有两个属性:
  • value: 迭代器一系列值的具体一个值,done=true时表示没有值了
    此时忽略value的值,这里经常误以为是最后一个值。上面列举的可迭代最新的遍历语法都会忽略done=truevalue.
  • done: 标记是否还具有下个值。

这样就可以获取迭代器一系列的值以及判断是否还具有更多的值。

3.2 可迭代协议(iterable protocol)和迭代器协议(iterator protocol)对比

两者是不同的:

  1. 前者定义如何遍历一个对象;
  2. 后者定义如何产生遍历的一系列值。

一个对象可能既是可迭代对象,也可能是迭代器。

四、实战

4.2 内置可迭代对象

  1. String
  2. Array, TypedArray,
  3. Set,
  4. Map
  5. 生成器generator对象
  6. arguments对象

内置可迭代对象返回的迭代器也是个可迭代对象

内置可迭代对象返回的迭代器也是个可迭代对象(额,有点绕~)并且两者的迭代器是相等的

const arr = [ 1, 2, 3 ]
const iter = arr[Symbol.iterator]()
for (const item of iter) {
    console.log(item) // 1 2 3
}
const iter2 = iter[Symbol.iterator]()
console.log(iter === iter2) // true
const iter3 = iter[Symbol.iterator]()[Symbol.iterator]()[Symbol.iterator]()
console.log(iter === iter3) // true

4.3 自定义可迭代对象

var iterableName = {
    [Symbol.iterator]: () => {
        var index = 0;
        var val = ['john', 'lucy']

        return {
            next: () => {
                return val.length === index ? {
                    done: true
                } : {
                    value: val[index++],
                    done: false
                }
            }
        }
    }
}

for(var a of iterableName) {
    console.log(a)    
}

// ['john', 'lucy']
[...iterable] 

代码输出判断:

var a = {
  [Symbol.iterator]: () => {
    var index = 0;
    return {
      next: () => {
        if(index === 3) {
          return {
            done: true,
            value: 9
          }
        }

        return {
          done: false,
          value: ++index
        }
      }
    }
  }
}

for(let v of a) {
  console.log(v)
}

参考

  1. MDN Iteration protocols
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant