let arr = ['a', 'b', 'c']; let iter = arr[Symbol.iterator](); iter.next() // { value: 'a', done: false...// { value: undefined, done: true } 但是如果 Symbol.iterator 方法对应的不是遍历器生成函数(即会返回一个遍历器对象),解释引擎将会报错。...方法的返回值不是一个对象 for (let item of obj) { console.log(item); } // 测试 2 // 下面我们让Symbol.iterator方法的返回值是一个对象...3、计算生成的数据结构 有些数据结构是在现有数据结构的基础上,计算生成的。比如,ES6 的数组、Set、Map 都部署了以下三个方法,调用后都返回遍历器对象。...这三个方法调用后生成的遍历器对象,所遍历的都是计算生成的数据结构。
这是因为生成的 Symbol 是一个原始类型的值,不是对象。也就是说,由于 Symbol 值不是对象,所以不能添加属性。基本上,它是一种类似于字符串的数据类型。...2、Symbol值不能与其他数据进行计算,包括同字符串拼串 let sym = Symbol('My symbol'); "your symbol is " + sym // TypeError: can't...7、Symbol.iterator 对象的Symbol.iterator属性,指向该对象的默认遍历器方法。...let arr = ['a', 'b', 'c']; let iter = arr[Symbol.iterator](); iter.next() // { value: 'a', done: false...} iter.next() // { value: 'b', done: false } iter.next() // { value: 'c', done: false } iter.next()
的情况,假如我们有一个Arrays,可以通过Symbol.iterator这个key来获取到Iterator: > const arr = ['a', 'b', 'c']; > const iter =...arr[Symbol.iterator](); > iter.next() { value: 'a', done: false } > iter.next() { value: 'b', done:...('div')) { ··· } 普通对象不是可遍历的 简单对象就是通过字面量创建出来的对象,这些对象虽然也有key-value的内容,但是是不可遍历的。...for (const x of {}) { // TypeError console.log(x); } 虽然不能直接遍历普通对象,但是我们可以通过使用objectEntries方法来遍历普通对象...先看下objectEntries的实现: function objectEntries(obj) { let iter = Reflect.ownKeys(obj)[Symbol.iterator
通过map[Symbol.iterator]()可以获取map的遍历器对象。...let arr = ['a', 'b', 'c']; let iter = arr[Symbol.iterator](); iter.next(); 调用Iterator接口的场景 一些场景会默认调用Iterator...但是,它也不是私有属性,有一个Object.getOwnPropertySymbols方法,可以获取指定对象的所有Symbol属性名。...let arr = ['a', 'b', 'c']; let iter = arr[Symbol.iterator](); iter.next() // { value: 'a', done: false...Proxy Proxy并不是以语法形成使用,而是一种包装器的形式使用。
let arr = ['a', 'b', 'c']; let iter = arr[Symbol.iterator](); iter.next() // { value: 'a', done: false...方法对应的不是遍历器生成函数(即会返回一个遍历器对象),解释引擎将会报错。...的Symbol.iterator方法对应的不是遍历器生成函数,因此报错。...有些数据结构是在现有数据结构的基础上,计算生成的。...这三个方法调用后生成的遍历器对象,所遍历的都是计算生成的数据结构。
let arr = ['a', 'b', 'c']; let iter = arr[Symbol.iterator](); iter.next() // { value: 'a', done: false...如果Symbol.iterator方法对应的不是遍历器生成函数(即会返回一个遍历器对象),解释引擎将会报错 var obj = {}; obj[Symbol.iterator] = () => 1;...[...obj] // TypeError: [] is not a function 上面代码中,变量obj的Symbol.iterator方法对应的不是遍历器生成函数,因此报错。...有些数据结构是在现有数据结构的基础上,计算生成的。...这三个方法调用后生成的遍历器对象,所遍历的都是计算生成的数据结构。
前言 记得刚找工作那会,几种数据类型是必问题,当时的答案一般都是七种——字符串(String)、数字(Number)、布尔(Boolean)、数组(Array)、对象(Object)、空(Null)、未定义...对symbol的描述,可用于调试但不是访问symbol本身。请注意,即使传入两个相同的字符串,得到的 symbol 也不相等。...下面带有 new 运算符的语法将抛出 TypeError 运算符的语法将抛出错误: var sym = new Symbol(); // TypeError 特性 正如歌词“每个人都有他的脾气”所说,Symbol...拥有 Symbol.iterator 函数的对象被称为 可迭代对象 ,就是说你可以在对象上使用 for/of 循环。...而不是字符串?
迭代强调依次取数据的过程,不保证把所有的数据都取完 遍历强调的是要把所有的数据依次全部取出 在JavaScript中,迭代器是能调用 next方法实现迭代的一个对象,该方法返回一个具有两个属性的对象。...迭代器简单使用 通过可迭代对象中的迭代器工厂函数 Symbol.iterator来生成迭代器。...但是,上面的说法并不是很准确,并不是迭代器下一个值 value为 undefined时,就完成的。还需要判断是不是真的没有值,还是是可迭代对象里就有一个值为 undefined。...1、2、3 } 迭代器”与时俱进” 如果可迭代对象在迭代期间被修改了,迭代器得到的结果也会是修改后的。...然而,并不是,迭代器会处于一种完成但并不完成的状态, done: true表示已经完成了,但是后续还能一直调用 next,虽然得到的结果一直都会是 { value: undefined, done: true
Lazy evaluation Lazy evaluation常被译为“延迟计算”或“惰性计算”,指的是仅仅在真正需要执行的时候才计算表达式的值。...充分利用惰性求值的特性带来的好处主要体现在以下两个方面: 避免不必要的计算,带来性能上的提升。 节省空间,使得无限循环的数据结构成为可能。...迭代器是一个可以被迭代的对象。它抽象了数据容器,使其行为类似于可迭代对象。 迭代器在实例化时不计算每个项目的值,仅在请求时才生成下一个值。 这非常有用,特别是对于大型数据集或无限个元素的序列。...JS 中的很多对象都是可迭代的,它们可能不是很好的察觉,但是如果仔细检查,就会发现迭代的特征: new Map([iterable]) new WeakMap([iterable]) new Set([...可迭代的协议 要使对象变得可迭代,它必须实现一个通过Symbol.iterator的迭代器方法,这个方法是迭代器的工厂。
,用于取出参数对象中的所有可遍历属性,浅拷贝到当前对象之中。...因为任何定义了遍历器(Iterator)接口的对象,都可以用扩展运算符转为真正的数组。...判断是否为实现了遍历器(Iterator)接口的对象,若实现了则转为数组。 如果没有实现遍历器(Iterator)接口的对象,则判断是否为普通字符串/Map/Set等。...判断是否为普调字符串/Map/Set等 _nonIterableSpread() // 则抛错 ); } function _nonIterableSpread() { throw new TypeError...== "undefined" && iter[Symbol.iterator] != null) || iter["@@iterator"] !
—— 《迭代器与生成器》(JavaScript 的延迟计算依赖的就是它),是重点毋庸置疑了。...数组中的每一项都只能先通过引用取得数组对象, 然后再通过[]操作符取得特定索引位置上的项。并且,这种情况并不适用于所有数据结构。 遍历顺序并不是数据结构固有的。...执行该函数 [Symbol.iterator](),会返回一个遍历器对象。只要数据结构拥有 Symbol.iterator属性,那么它就是 “可遍历的” 。...---- 所有拥有 Symbol.iterator 的对象被称为可迭代的。...[Symbol.iterator](); console.log(iter.next()); // { done: false, value: 'foo' } console.log(iter.next
)数组解构const arr = [1, 2, 3];const [a, b] = arr;console.log(a, b)工作中我们最经常用的就是类似上面的对象和数组解构,好多同学就不禁问了,这个不是很简单吗...可迭代协议 中必须有这么一个属性:Symbol.iterator,一个无参数的函数,其返回值为一个符合 可迭代协议 的对象,即迭代器。数组解构数组可以解构,因为数组是一个可迭代对象。...const arr = [1, 2, 3];const iter = arr[Symbol.iterator]();console.log(iter.next())console.log(iter.next...a = iter.next().value;const b = iter.next().value;console.log(a, b)对象解构那么问题来了,对象身上没有 Symbol.iterator...如果你对这些还不是很熟悉,建议你看一下 ES6 的文档:ECMAScript 6 入门教程
对象并不是 iterable(可遍历的)。...(value);} // 1// 2// 3 由此,我们也可以发现 for of 遍历的其实是对象的 Symbol.iterator 属性。...== "function") throw new TypeError("cb must be callable"); iterable = obj[Symbol.iterator]();...表达式,并判断表达式的结果来决定是否执行循环体,如果 test 计算结果为真值,则执行循环体中的 statement。...,仅仅是在有 return 函数的时候执行了 return 函数而已,return 函数中返回的值其实并不生效…… 但是你不返回值或者返回一个基本类型的值的话,结果又会报错…… TypeError: Iterator
对象并不是 iterable(可遍历的)。...console.log(value); } // 1 // 2 // 3 由此,我们也可以发现 for of 遍历的其实是对象的 Symbol.iterator 属性。...== "function") throw new TypeError("cb must be callable"); iterable = obj[Symbol.iterator]();...test 表达式,并判断表达式的结果来决定是否执行循环体,如果 test 计算结果为真值,则执行循环体中的 statement。...,仅仅是在有 return 函数的时候执行了 return 函数而已,return 函数中返回的值其实并不生效…… 但是你不返回值或者返回一个基本类型的值的话,结果又会报错…… TypeError: Iterator
,每个迭代器都会关联一个可迭代对象,迭代器会暴露其关联可迭代对象的API 任何实现iterable接口的数据结构都可以被实现iterator接口的结构进行迭代。...可迭代协议 实现 Iterable 接口(可迭代协议)要求同时具备两种能力:支持迭代的自我识别能力和创建实现 Iterator 接口的对象的能力。...next()方法返回的迭代器对象 IteratorResult 包含两个属性:done 和 value。...,如果在迭代期间被修改,迭代器也会马上反映相应的变化 let arr = ['foo', 'baz']; let iter = arr[Symbol.iterator](); console.log(...(iter.next()); // { done: true, value: undefined } 注意:迭代器维护着一个指向可迭代对象的引用,因此迭代器会阻止垃圾回收程序回收可迭代对象。
@@ 表示法有点误导性,我们真正 要做的是用预定义的 Symbol.iterator 符号定义方法。...但是调用的结果不是对象。...object 这次 javascript 告诉我们它试图调用 Symbol.iterator 方法,而该对象的确是一个对象,并且实现了 next 方法,但是 next 的返回值不是 javascript...} const foo = new First20Evens; for(const value of foo) { console.log(value) } 生成器 手动去构建实现迭代器协议的对象不是唯一的选择...今天的重要收获是,我们可以使自己的 Symbol.iterator 方法返回一个生成器对象,并且该生成器对象能够在 for ... of 循环中“正常工作”。
不断调用指针对象的next方法,直到它指向数据结构的结束位置 2.3 Symbol.iterator属性 2.3.1 简介 ES6 规定,默认的 Iterator 接口部署在数据结构的Symbol.iterator...示例 let arr = [1, 2, 3] let iter = arr[Symbol.iterator]() console.log(iter.next()); console.log(iter.next...()); console.log(iter.next()); console.log(iter.next()); 运行结果: { value: 1, done: false } { value: 2..., done: false } { value: 3, done: false } { value: undefined, done: true } 其中,上面的iter返回的是一个迭代器对象,由于...2.3.3 对象的Iterator 一个对象如果要具备可被for…of循环调用的 Iterator 接口,就必须在Symbol.iterator的属性上部署遍历器生成方法(原型链上的对象具有该方法也可)
这在以下代码中偶尔会有用,当你想要遍历“部分使用过”的迭代器时: let list = [1,2,3,4,5]; let iter = list[Symbol.iterator](); let head...相反,基于 Promise 的异步计算将异常(通常作为某种类型的 Error 对象,尽管这不是必需的)传递给then()的第二个函数。...Reflect.ownKeys(o) 此函数返回对象o的属性名称的数组,如果o不是对象则抛出 TypeError。返回的数组中的名称将是字符串和/或符号。...成功时返回true,失败时返回false(如果属性是只读的,则可能失败)。如果o不是对象,则抛出 TypeError。...如果o不是对象或p既不是对象也不是null,则抛出 TypeError。Object.setPrototypeOf()类似,但成功时返回o,失败时抛出 TypeError。
领取专属 10元无门槛券
手把手带您无忧上云