资讯专栏INFORMATION COLUMN

ES6 迭代协议

sunny5541 / 1094人阅读

摘要:迭代协议可迭代协议和迭代器协议是对的补充,不是新的内置或语法,仅仅是协议。迭代器协议例子简单迭代器生成器再谈生成器从上面的示例可以看出,是比较特殊的,既是一个生成器对象,又是一个可迭代对象文章若有纰漏,欢迎大家提问交流参考

迭代协议

可迭代协议(The iterable protocol) 和 迭代器协议(The iterator protocol)是对 ECMAScript 2015 的补充,不是新的内置或语法,仅仅是协议。可以被任何遵循某些约定的对象来实现。

可迭代协议

可迭代协议允许 JavaScript 对象去定义或者定制它们的迭代行为。

一些内置类型是可迭代,例如 Array,TypeArray,Map,Set,String,在 for...of 结构中可以循环遍历值,而 Object 就不是。

为了变成可迭代对象,一个对象必须实现 @@iterator 方法, 意思是这个对象(或者它原型链 prototype chain 上的某个对象)必须有一个名字是 Symbol.iterator 的属性:

Property Value
[Symbol.iterator] 无参函数,该函数返回一个对象,该对象符合迭代器协议
迭代器协议

迭代器协议定义了一种标准的方式来产生有限或无限序列的值

当一个对象实现了 next() 方法,并且符合如下定义,则该对象就是一个迭代器对象。

属性
next 一个无参函数,返回一个对象,该对象拥有两个属性 done 和 value
done(boolean)

如果迭代器已经到了迭代序列的末尾,done 为 false

如果迭代器还可以产生序列下一个值,done 为 true

value

迭代器返回的任何 JavaScript 值,当 done 为 true,可忽略。

next 方法必须是返回包含 done 和 value 属性的对象,如果非对象(类如 false, undefined)返回,将会抛出 TypeError

例子 可迭代协议例子
自定义一个可迭代对象
const iterableObj = {}
iterableObj[Symbol.iterator] = function* () {
    yield 1
    yield 2
    yield 3
}
console.log([...iterableObj])
接受可迭代对象的内置 APIs

许多 APIs 接受可迭代对象作为参数,例如 Map([iterable]),WeakMap([iterable]),Set([iterable]),WeakSet([iterable])

const myObj = {}
new Map([[1, "a"], [2, "b"], [3, "c"]]).get(2)               // "b"
new WeakMap([[{}, "a"], [myObj, "b"], [{}, "c"]]).get(myObj) // "b"
new Set([1, 2, 3]).has(3)                                    // true
new Set("123").has("2")                                      // true
new WeakSet(function* () {
    yield {}
    yield myObj
    yield {}
}()).has(myObj)                                              // true
用于可迭代对象的语法

一些语句或者表达式可用于可迭代对象,例如 for...of 循环,spread operator,yield*,destructuring assignment。

// for...of
for (let i of [1, 2, 4]) {
    console.log(i)
    // 1
    // 2
    // 4
}

// spread operator
console.log([..."abc"]) // ["a", "b", "c"]

// yield*
function* gen() {
    yield* ["a", "b", "c"]
}
console.log(gen().next()) // {value: "a", done: false}

// destructuring assignment
[a, b] = new Set(["a", "b"])
console.log(a) // a
迭代器协议例子
简单迭代器
function makeIterator(array) {
    let nextIndex = 0
    return {
        next() {
            return nextIndex < array.length ? { value: array[nextIndex++], done: false } : { done: true }
        }
    }
}

const it = makeIterator(["a", "b"])

console.log(it.next()) // {value: "a", done: false}
console.log(it.next()) // {value: "a", done: false}
console.log(it.next()) // {done: true}
生成器
function* makeSimpleGenerator(arr) {
    let nextIndex = 0
    while (nextIndex < array.length) {
        yield array[nextIndex++]
    }
}

const it = makeSimpleGenerator(["a", "b"])

console.log(it.next()) // {value: "a", done: false}
console.log(it.next()) // {value: "a", done: false}
console.log(it.next()) // {value: undefined, done: true}
ES6 class
class SimpleIterator {
    constructor(data) {
        this.data = data
        this.index = 0
    }

    [Symbol.iterator]() {
        return {
            next: () => {
                return this.index < this.data.length ? { value: this.data[this.index++], done: false } : { done: true }
            }
        }
    }
}

const simple = new SimpleIterator([1, 3, 9])

for (let i of simple){
    console.log(i) // 1 3 9
}
再谈生成器 generator

从上面的示例可以看出,generator 是比较特殊的,generator 既是一个 生成器对象,又是一个 可迭代对象!

const generatorObj = function* () {
    yield 1
    yield 2
    yield 3
}()

console.log(typeof generatorObj.next) // function

console.log(typeof generatorObj[Symbol.iterator]) // function

console.log(generatorObj[Symbol.iterator]() === generatorObj) // true

文章若有纰漏,欢迎大家提问交流!

参考

MDN: Iteration protocols

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/107198.html

相关文章

  • ES6语法之可迭代协议迭代协议

    摘要:有两个协议可迭代协议和迭代器协议。为了变成可迭代对象,一个对象必须实现或者它原型链的某个对象必须有一个名字是的属性迭代器协议该迭代器协议定义了一种标准的方式来产生一个有限或无限序列的值。 ECMAScript 2015的几个补充,并不是新的内置或语法,而是协议。这些协议可以被任何遵循某些约定的对象来实现。有两个协议:可迭代协议和迭代器协议。 可迭代协议 可迭代协议允许 JavaScri...

    sarva 评论0 收藏0
  • ES6学习(二)之解构赋值及其原理

    摘要:基本原理解构是提供的语法糖,其实内在是针对可迭代对象的接口,通过遍历器按顺序获取对应的值进行赋值。属性值返回一个对象的无参函数,被返回对象符合迭代器协议。迭代器协议定义了标准的方式来产生一个有限或无限序列值。 更多系列文章请看 1、基本语法 1.1、数组 // 基础类型解构 let [a, b, c] = [1, 2, 3] console.log(a, b, c) // 1, 2, ...

    chunquedong 评论0 收藏0
  • 从forEach到迭代

    摘要:本文从使用对数组进行遍历开始说起,粗略对比使用进行遍历的差异,并由此引入中可迭代对象迭代器的概念,并对其进行粗略介绍。说到这里,就继续说一下迭代器关闭的情况了。确实,符合可迭代协议和迭代器协议的。 本文从使用 forEach 对数组进行遍历开始说起,粗略对比使用 forEach , for...in , for...of 进行遍历的差异,并由此引入 ES6 中 可迭代对象/迭代器 的概...

    rockswang 评论0 收藏0
  • 迭代器模式到迭代协议

    摘要:迭代器模式迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而不需要暴露该对象的内部表示。可迭代协议和迭代器协议。生成器函数是可以作为迭代器工厂的函数,当它被执行时会返回一个新的对象,该对象符合可迭代协议和迭代器协议。 迭代器模式 迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而不需要暴露该对象的内部表示。 迭代器分为内部迭代器和外部迭代器。内部迭代器只需一次初...

    doodlewind 评论0 收藏0
  • ES6的Iterator对象详解

    摘要:实现原理创建一个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上,就是一个指针对象。具体来说,就是返回一个包含和两个属性的对象。接口部署在对象的属性上可以调用这个属性,就得到遍历器对象。 Iterator实现原理 创建一个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上,就是一个指针对象。 第一次调用指针对象的next方法,可以将指针指向数据结构的第一...

    KoreyLee 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<