Symbol.iterator
为每一个对象定义了默认的迭代器。该迭代器可以被for……of
循环使用
具有如下属性:
writable
(可写)、enumerable
(可迭代)、configurable
(可修改,可删除)
- 当需要对一个对象进行迭代时,它的
@@iterator
方法都会在不传参的情况下被调用,返回的迭代器用于获取要迭代的值。(一些内置类型拥有默认的迭代器行为,其他类型【如Object
】则没有。
-
自定义迭代器(在具体需求的情况下)
var myIterable = {} //Object没有默认的迭代器行为的情况下,创建自定义迭代器 myIterable[Symbol.iterator] = function *(){ //创建Generator函数实现 yield 1; yield 2; yield 3; }; [...myIterable] //使用展开运算符直接以数组的形式输出==》[1,2,3]
-
迭代协议并非新的内置实现或语法,而是协议。这些协议可被任何遵循某些约定的对象来实现
迭代协议具体分为两个协议:可迭代协议和迭代器协议
-
可迭代协议允许
JavaScript
对象定义或定制它们的迭代行为,例如,在一个for……of
结构中,哪些值可以被遍历到。一些内置类型同时是内置可迭代对象【String
、Array
、TypedArray
、Map
、Set
】,并且由默认的迭代行为。【需要可迭代对象的语法:for……of
循环、展开语法、yield*
、解构赋值】要成为 可迭代对象,必须实现 **
@@iterator
**方法。也就意味着对象(或它原型链上的某个对象)必须有一个键为@@iterator
的属性,并可通过常量Symbol.iterator
访问该属性 -
迭代器协议定义了产生一系列值(无论是有限个还是无限个)的标准方法。
只有实现了一个拥有以下语义的
next()
方法,一个对象才能成为迭代器属性:
next
、值(一个无参数或者一个参数的函数,返回一个应当拥有以下两个属性的对象:done(boolen)
【是否产生序列中的下一个value
】 +value
【迭代器返回的任何JavaScript
值,done
为true
时可省略】next()
方法必须返回一个对象,该对象应当有两个属性:done
和value
-
String
是一个内置的可迭代对象,默认迭代器会依次返回该字符串的各码点(code point
);let someString = 'hi'; console.log(typeof someString[Symbol.iterator]); //function,具有参数方法【next() 返回两个值:done和value】
let someString = 'hi'; let iterator = someString[Symbol.iterator](); //调用自身对象方法 iterator + ''; console.log(iterator.next()); //每次执行next()方法,输出一个code pint console.log(iterator.next()); console.log(iterator.next());
-
一些内置的语法结构——比如
展开语法
——其内部实现也使用了同样的迭代协议let someString = 'hi'; console.log([...someString]) //相当于直接调用for……of进行循环输出
-
-
-
简单迭代器
//只有实现了一个拥有以下语义(semantic)的 next() 方法,一个对象才能成为迭代器 //一个无参数或者一个参数的函数,返回一个应当拥有以下两个属性的对象 //以上两句话的解读如下函数实现 function makeIterator(array) { //自定义一个方法,具备iterator迭代器的结构语法 let nextIndex = 0; return { //必须有return next: function () { return nextIndex < array.length ? { //三元运算来动态修改done的布尔值 value: array[nextIndex++], //返回value和done done: false, } : { done: true, //改变done的布尔值 }; }, }; } let it = makeIterator(['哟', '呀']); console.log(it.next().value); console.log(it.next().value); console.log(it.next().value);