// iterable:一个具有可枚举属性并且可以迭代的对象。...,它还从构造函数的原型中查找继承的非枚举属性; for...of 不考虑构造函数原型上的不可枚举属性(或者说for...of语句遍历可迭代对象定义要迭代的数据。)...简单来说,for of 语句创建一个循环来迭代可迭代的对象,可迭代的对象内部实现了Symbol.iterator方法,而普通对象没有实现这一方法,所以普通对象是不可迭代的。...有一些场合会默认调用 Iterator 接口(即Symbol.iterator方法: 扩展运算符...:这提供了一种简便机制,可以将任何部署了 Iterator 接口的数据结构,转为数组。...数组和可迭代对象的解构赋值(解构是ES6提供的语法糖,其实内在是针对可迭代对象的Iterator接口,通过遍历器按顺序获取对应的值进行赋值。
可以把可迭代对象理解成数组或集合这样的集合类型的对象,其包含的元素是有限的,而且都具有无歧义的遍历顺序。...(可迭代对象不一定是集合对象,可以是具有类似数组行为的其他数据结构) 任何实现Iterable接口的数据结构都可以被实现Iterator接口的结构消费。迭代器是按需创建的一次性对象。...等DOM集合类型 接收可迭代对象的原生语言特性 for-of循环 数组解构 扩展符操作 Array.from() 创建集合 创建映射 Promise.all()接收由Promise组成的可迭代对象 Promise.race...,所以并非所有迭代器都是可关闭的 要知道某个迭代器是否可关闭,可测试这个迭代器实例的return属性是不是函数 仅仅给一个不可关闭的迭代器增加return方法不能让他变成可关闭的,因为调用return...类似函数的return关键字,yield关键字必须直接位于生成器函数定义中,出现在嵌套的非生成器函数中会抛出语法错误 // 无效 function* invalidGeneratorFnA() {
对象必须实现@@iterator方法,意味着对象必须有一个带有@@iterator key的可以通过常量Symbol.iterator访问到的属性。...实现了生成迭代器方法的对象称为 可迭代对象 也就是说这个对象中包含一个方法, 该方法返回一个迭代器对象 一般使用 Symbol.iterator来定义该属性, 学名叫做 @@iterator 方法 /.../ 一个可迭代对象需要具有[Symbol.iterator]方法,并且这个方法返回一个迭代器 const obj = { names: ['111', '222', '333'], [Symbol.iterator...一个数据结构只要部署了Symbol.iterator属性,就被视为具有iterator接口,可以使用for of,它可以循环可迭代对象。...返回的结果是一个对象,对象中包含了当前值value 和 当前是否结束done 遍历对象 尝试遍历一下对象,我们会发现他报这个对象是不可迭代的,如下图 那我们可以使用上面的迭代器对象生成器让对象也支持for
迭代过程 迭代的过程如下: 通过 Symbol.iterator 创建一个迭代器,指向当前数据结构的起始位置 随后通过 next 方法进行向下迭代指向下一个位置, next 方法会返回当前位置的对象,对象包含了...,然后通过 Symbol.iterator 方法创建一个迭代器,之后不断的调用 next 方法对数组内部项进行访问,当属性 done 为 true 时访问结束。...entries ,每个 entry 都会被编码为 key, value 的项, entries 是以确定的形势进行迭代,其顺序是与添加的顺序相同。...); } } args("zero", "one"); // output: // zero // one 普通对象不可迭代 普通对象是由 object 创建的,不可迭代: // TypeError...of 操作数必须是可迭代,这意味着如果是普通对象则无法进行迭代。
,它是通过一个键为Symbol.iterator 的方法来实现。...迭代过程 迭代的过程如下: 通过 Symbol.iterator 创建一个迭代器,指向当前数据结构的起始位置 随后通过 next 方法进行向下迭代指向下一个位置, next 方法会返回当前位置的对象,对象包含了...,然后通过 Symbol.iterator 方法创建一个迭代器,之后不断地调用 next 方法对数组内部项进行访问,当属性 done 为 true 时访问结束。...,每个 entry 都会被编码为 key, value 的项, entries 是以确定的形式进行迭代,其顺序是与添加的顺序相同。...of 操作数必须是可迭代,这意味着如果是普通对象则无法进行迭代。
,其它属性(索引)为非负整数 不具有数组所具有的方法 常见的类数组有arguments和NodeList, 《javascript权威指南》里面给出了一个鉴别对象是否是类数组的函数 function...,可以将两类对象转为真正的数组:类数组对象和可遍历(iterable)对象(包括ES6新增的数据结构Set和Map); 方法可以将类数组对象和可迭代对象转换为数组。...Array、Set、Map 和字符串都是可迭代对象(WeakMap / WeakSet 并不是可迭代对象) 字符串变成了可迭代对象,解决了编码的问题 这些对象都有默认的迭代器,即具有 Symbol.iterator...扩展运算符(…) 同样是ES6中新增的内容,扩展运算符(…)也可以将某些数据结构转为数组 3.1 arguments对象的转换 function foo() { var...(obj) 默认情况下,开发者定义的对象都是不可迭代对象,但提供了返回迭代器的方法 entries() values() keys() 通过使用这些方法,可以返回相关的数组 与类数组对象需要对象有
getIterator方法返回一个对象 - 可迭代对象 对象具有一个next 方法,next 方法内部通过闭包来保存指针 i 的值,每次调用 next 方法 i 的值都会+1....ES6里规定,只要在对象的属性上部署了Iterator接口,具体形式为给对象添加Symbol.iterator属性,此属性指向一个迭代器方法,这个迭代器会返回一个特殊的对象 - 迭代器对象。...扩展运算符 扩展运算符的执行(...)也会默认调用它的Symbol.iterator方法,可以将当前迭代对象转换为数组。...判断对象是否可迭代 既然可迭代对象的规则必须在对象上部署Symbol.iterator属性,那么我们基本上就可以通过此属来判断对象是否为可迭代对象,然后就可以知道是否能使用 for of 取值了。...而 for of 执行的时候引擎会自动调用对象的迭代器来取值。 不是所有的对象都支持这种方式,必须是实现了Iterator接口的才可以,这样的对象我们称他们为可迭代对象。
让我们看看什么是可迭代的,以及如何使对象可迭代。...让我们将这个方法命名为 --- iteratorMethod ECMA 也采取了类似的步骤来标准化在定制对象上循环的过程。...同时,Symbol.iterator 返回一个名为迭代器的对象,这个迭代器将拥有一个名为next的方法,该方法将返回一个具有键值为 value 和 done 的对象。...image.png 根据Axel Rauschmayer博士的《探索JS》一书: 可迭代是一种数据结构,它希望使其元素对外部可访问,通过实现一个关键字是Symbol.iterator的方法来实现,该方法是迭代器的工厂...JavaScript中可迭代对象(iterable) JS 中的很多对象都是可迭代的。
要使类可迭代,必须实现一个方法,其名称为符号Symbol.iterator。该方法必须返回具有next()方法的迭代器对象。...而next()方法必须返回具有value属性和/或布尔done属性的迭代结果对象。示例 12-1 实现了一个可迭代的 Range 类,并演示了如何创建可迭代、迭代器和迭代结果对象。 示例 12-1....(正如我们之前看到的,for/await与常规可迭代对象兼容,但它更喜欢异步可迭代对象,并在尝试Symbol.iterator方法之前尝试Symbol.asyncIterator方法。)...此外,尝试更改不可扩展对象的原型(参见§14.3)将始终抛出 TypeError。 请注意,一旦将对象设置为不可扩展,就没有办法再使其可扩展。...另外,请注意,调用Object.preventExtensions()只影响对象本身的可扩展性。如果向不可扩展对象的原型添加新属性,那么不可扩展对象将继承这些新属性。
让我们将这个方法命名为 --- iteratorMethod ECMA 也采取了类似的步骤来标准化在定制对象上循环的过程。...同时,Symbol.iterator 返回一个名为迭代器的对象,这个迭代器将拥有一个名为next的方法,该方法将返回一个具有键值为 value 和 done 的对象。...根据Axel Rauschmayer博士的《探索JS》一书: 可迭代是一种数据结构,它希望使其元素对外部可访问,通过实现一个关键字是Symbol.iterator的方法来实现,该方法是迭代器的工厂,也就是说...它是一个定义了next方法的对象。next方法根据step变量返回值。在第25行,我们检索iterator,27行,我们调用next方法,直到 done的值为 true。...JavaScript中可迭代对象(iterable) JavaScript中的很多对象都是可迭代的。
一、Iterator(遍历器)的存在 1、迭代器模式 迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。...在使用迭代器模式之后,即使不关心对象的内部构造,也可以按顺序访问其中的每个元素。...以上数据类型,都有 Symbol.iterator 属性,属性值是一个函数,执行这个函数就会返回一个迭代器。这个迭代器就有 next 方法可顺序迭代子元素。...for…of循环调用的 Iterator 接口,就必须在Symbol.iterator 的属性上部署遍历器生成方法(原型链上的对象具有该方法也可)。...某些情况下,for...in 循环会以任意顺序遍历键名。 总之,for...in 循环主要是为遍历对象而设计的,不适用于遍历数组。
迭代器是如何设计的 有两种定义迭代器的方法,分别是独立定义与合并在对象里定义。 独立定义 为对象拓展 [Symbol.iterator] 属性即可。...合并在对象里定义 简化一点可以将迭代定义在对象里: let range = { from: 1, to: 5, [Symbol.iterator]() { this.current...读过上面的介绍,你应该理解到可迭代的原因是实现了 [Symbol.iterator],而与对象是否是数组,或者 ArrayLike 没有关系。...// ... }; // 该对象不可迭代,是 ArrayLike const range = { "0": "a", "1": "b", length: 2, }; // 该对象可迭代...一个对象黑盒,不论内部怎么实现,如果我们能按照顺序数出内部结构,那么这个对象就是可迭代的,这就是 [Symbol.iterator] 定义要解决的问题。
arr,调用 arr 的 Symbol.iterator 方法创建了一个迭代器对象 iterator 之后不断调用 next 方法返回当前数组内容,直到 next 方法返回值 done 为 true...注意 Map 调用 Symbol.iterator 方法返回的是一个 entries 方法,该方法返回的是一个新的迭代器对象且按插入顺序包含了 Map 对象中每个元素的 [key, value] 数组,...ES6 中的扩展运算符(...)也会默认调用数组、Set、Map 等结构的 Symbol.iterator 方法。...迭代协议 参照可迭代协议,要成为可迭代对象首先要有一个 **@@iterator **即(Symbol.iterator)属性,该属性为一个无参数的函数,返回一个符合迭代器协议的对象。...同步可迭代协议具有 Symbol.iterator 属性,异步可迭代协议具有 Symbol.asyncIterator 属性。
❞ new Set([ iterable ]) 可以传递一个可迭代对象,它的所有元素将被添加到新的 Set中。如果不指定此参数或其值为null,则新的 Set为空。...) 返回一个新的迭代器对象,该对象包含Set对象中的按插入顺序排列的所有元素的值。...Set.prototype.entries() 返回一个新的迭代器对象,该对象包含Set对象中的按插入顺序排列的所有元素的值的[value, value]数组。...,原因也是我们给Set、keys、values、entries部署了Symbol.iterator,使之具有“iterator”接口,而扩展运算符...的特点之一就是任何具有Iterator接口的对象,...都可以用扩展运算符转为真正的数组。
2、同步迭代器 以常见的数组打印为例,下述代码会依次打印出 "0、1": for(const cur of [0, 1]){ console.log(cur); } 那么如何用 同步迭代器 实现上述同等输出...该 next 函数返回值必须返回包含 done 和 value 这两个字段的对象 有了 Iterator,就可以借助 [Symbol.iterator] 构造出 可迭代对象(Iteratable):...() { // 返回一个迭代器对象,对象的属性是一个 next 方法 return { next: function () { if (count...true return { value: count, done: true }; } }; } 然后创建出可迭代对象,由于该对象的行为和 [0,1] 这个数组类似...(cur) } 通过这个例子你就应该比较容易迭代器的理解,其实 JS 原生的String、Array、Map 和 Set 等都是可迭代对象,因为它们的原型对象都有一个 Symbol.iterator 方法
遍历顺序并不是数据结构固有的。 通过递增索引来访问数据是特定于数组类型的方式,并不适 用于其他具有隐式顺序的数据结构。 什么意思?...for-in 是为遍历普通对象设计的,可以得到字符串类型的键,不适用于数组遍历。 for-of 呢?没错,它是今天的主角!...for-of 循环语句通过方法调用来遍历各种集合:数组、NodeList、字符串、Maps 对象、Sets 对象等等 这些对象都有一个共通的特点:它们都有一个迭代器方法!...执行该函数 [Symbol.iterator](),会返回一个遍历器对象。只要数据结构拥有 Symbol.iterator属性,那么它就是 “可遍历的” 。...---- 所有拥有 Symbol.iterator 的对象被称为可迭代的。
value ,通过索引判断得到 done ,当无数据可用时,超过数组最大索引,无可用数据返回,此时 done 为 true 可迭代对象 了解过了 iterator,并且我们也已经知道了如何创建一个遍历器对象..., 依次执行迭代器对象的 next 方法,将 next 方法的返回值赋值给 for ...of 内的变量,从而得到具体的值,实现遍历。...手写实现可迭代对象 一个数据结构只要具有 Symbol.iterator 属性,就可以认为是“可遍历的”。...也就是说要实现可迭代对象只要在对象上部署了Symbol.iterator属性,为它创建一个迭代器方法就可以了 let iteratorObj = { items: [1, 2, 'ljc'],...扩展运算符 扩展运算符也会默认调用Symbol.iterator方法,可以将当前数据结构转化为数组 // 阮老师的例子 var str = 'hello'; [...str] // ['h','e',
,并且for...of可以中断循环,关于循环中断可以参考以前写的一篇文章你不知道的JS循环中断 因为数组是支持可迭代的对象,如果使用迭代器获取每组数据应该怎么做呢?...方法,再调用返回的next方法,最后得到当前的值 我们可以在控制台看下 数组是有这个Symbol.iterator属性的 从以上迭代器特征中,我们可以得知,数组是通过一个Symbol.iterator...可访问的方法,并返回一个迭代器对象,迭代器对象可以调用`next`方法,在next方法中返回一个当前对象的值 [Symbol.iterator]: function () { let...因此让一个对象支持迭代器功能,只需要新增一个Symbol.iterator方法,遵循迭代器原则 支持所有对象可迭代 我们从以上结果得知要想一个对象支持迭代器功能,必须要有Symbol.iterator...生成器函数调用返回的是一个迭代器,具备迭代器所有特性,yield这个状态机只能在生成器函数内部使用 以实际例子对对象扩展支持迭代器特性,如果需要支持迭代器特征,那么必须原型上扩展Symbol.iterator
领取专属 10元无门槛券
手把手带您无忧上云