TypeScript迭代器

迭代器

重写迭代器要领需 ECMAScript 2015(ES6) , TypeScript 需 1.5 以上版本。

可迭代协定

可迭代协定 许可 JavaScript 对象去定义或定制它们的迭代行动, 比方(定义)在一个 for..of 构造中什么值能够被轮回(获得)。一些内置范例都是内置的可遍历对象并且有默许的迭代行动, 比方 Array or Map, 另一些范例则不是 (比方Object) 。

为了变成可遍历对象, 一个对象必需完成 @@iterator 要领, 意义是这个对象(或许它原型链prototype chain上的某个对象)必需有一个名字是 Symbol.iterator 的属性:

运用迭代器

以下代码悉数运用 TypeScript, TypeScript 版本号为 2.0.10, 运用 ES6 范例。

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 对象。

注重:箭头函数 没法作为生成器函数。

  1. 生成器

    >生成器是一种能够从中退出并在以后从新进入的函数。生成器的环境(绑定的变量)会在每次实行后被保留,下次进入时可继承运用。
  2. yield

    >yield 关键字用来停息和恢复一个生成器函数 ( (function* 或 legacy generator).
  3. yield*

    >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 系列接口要方便快捷的多。
    原文作者:不会爬树的猴
    原文地址: https://segmentfault.com/a/1190000008859289
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞