重写迭代器方法需 ECMAScript 2015(ES6) , TypeScript 需 1.5 以上版本。函数
可迭代协议 容许 JavaScript 对象去定义或定制它们的迭代行为, 例如(定义)在一个 for..of 结构中什么值能够被循环(获得)。一些内置类型都是内置的可遍历对象而且有默认的迭代行为, 好比 Array or Map, 另外一些类型则不是 (好比Object) 。this
为了变成可遍历对象, 一个对象必须实现 @@iterator 方法, 意思是这个对象(或者它原型链prototype chain上的某个对象)必须有一个名字是 Symbol.iterator 的属性:prototype
如下代码所有使用 TypeScript, TypeScript 版本号为 2.0.10, 使用 ES6 规范。code
var someArray = [1, 5, 7]; var someArrayEntries = someArray.entries(); console.log(someArrayEntries.toString()); // "[object Array Iterator]" console.log(someArrayEntries === someArrayEntries[Symbol.iterator]()); // true console.log([...someArray] ); //[1,5,7] let iterator = someArrayEntries[Symbol.iterator](); console.log(iterator.next()); console.log(iterator.next()); console.log(iterator.next()); //[Symbol.iterator] 返回一个对象的无参函数,被返回对象需符合迭代器协议。
someArray[Symbol.iterator] = ()=>{ return { _index:0, next: function() { if(this._index < someArray.length ){ return { value: someArray[this._index++], done: false} }else{ return { value: undefined, done:true} } }, [Symbol.iterator]:()=>{ return this; } }; }; //在js文件中,能够省略掉对 [Symbol.iterator] 属性的定义。 //next() 返回的数据中, //done为布尔值,按照约定应为是否已经进行到函数边界的描述 //value 则为当前可迭代对象的某个属性值。在js文件中, done为true 可省略。但实际上,value能够为任何js对象 let someArrayIterator = someArray[Symbol.iterator](); console.log(someArrayIterator.next()); //{ value: 1, done: false } console.log(someArrayIterator.next()); //{ value: 5, done: false } console.log(someArrayIterator.next()); //{ value: 7, done: false } console.log(someArrayIterator.next()); //{ value: undefined, done: true } console.log(someArrayIterator.next()); //{ value: undefined, done: true } someArrayEntries[Symbol.iterator] = ()=>{ return { _index:0, next: function() { if(this._index < someArray.length){ return { value: [this._index,someArray[this._index++]], done: false} }else{ return { value: [this._index,undefined], done:true} } }, [Symbol.iterator]:()=>{ return this; } }; }; console.log(someArrayEntries === someArrayEntries[Symbol.iterator]()); //false iterator = someArrayEntries[Symbol.iterator](); console.log(iterator.next()); //{ value: [ 0, 1 ], done: false } console.log(iterator.next()); //{ value: [ 1, 5 ], done: false } console.log(iterator.next()); //{ value: [ 2, 7 ], done: false } console.log(iterator.next()); //{ value: [ 3, undefined ], done: true } console.log(iterator.next()); //{ value: [ 3, undefined ], done: true }
for(let obj of someArray){ console.log(obj); } // 1 5 7 let someArrayIterator = someArray[Symbol.iterator](); let obj = someArrayIterator.next(); while(!obj.done){ console.log(obj.value) obj = someArrayIterator.next(); } // 1 5 7 //这里使用 while 来 模拟一部分 for...of 的逻辑。 console.log([...someArray] ); // [ 1, 5, 7 ] console.log([...someArrayEntries]);//[ [ 0, 1 ], [ 1, 5 ], [ 2, 7 ] ] //内置可迭代对象皆可以使用上述2种语法进行遍历其键值对。 //String, Array, TypedArray, Map and Set 是内置可迭代对象, 由于它们的原型对象都有一个 @@iterator 方法。 //除此以外由用户本身实现的 @@iterator 方法也可使用上述2中语法。
function* 声明 (function关键字后跟一个星号)定义了一个生成器函数 (generator function),它返回一个 Generator 对象。对象
注意:箭头函数 没法做为生成器函数。接口
生成器ip
>生成器是一种能够从中退出并在以后从新进入的函数。生成器的环境(绑定的变量)会在每次执行后被保存,下次进入时可继续使用。
yield原型链
>yield 关键字用来暂停和恢复一个生成器函数 ( (function* 或 legacy generator).
yield*generator
>yield* 能够把须要 yield 的值委托给另一个生成器或者其余任意的可迭代对象。
function* anotherGenerator(i) { yield i + 1; //yield 会返回当前语句的值,相似于return。但在生成器函数中,return受到使用限制。 yield i + 2; yield i + 3; } function* generator(i){ yield i; yield* anotherGenerator(i); yield i + 10; } var gen = generator(10); //执行生成器函数会返回一个生成器,保存了当前函数运行环境上下文,同时定义了next()方法来恢复函数运行直至下一条yield语句。 console.log(gen.next().value); // 10 console.log(gen.next().value); // 11 console.log(gen.next().value); // 12 console.log(gen.next().value); // 13 console.log(gen.next().value); // 20 //使用生成器函数来实现迭代功能,很显然比以前实现 Iterator 系列接口要方便快捷的多。