资讯专栏INFORMATION COLUMN

TypeScript迭代器

VishKozus / 2077人阅读

摘要:迭代器重写迭代器方法需需以上版本。返回一个对象的无参函数,被返回对象需符合迭代器协议。重写迭代器在文件中可以省略掉对属性的定义。但实际上可以为任何对象内置迭代器行为这里使用来模拟一部分的逻辑。

迭代器

重写迭代器方法需 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 对象。

注意:箭头函数 无法作为生成器函数。

生成器

>生成器是一种可以从中退出并在之后重新进入的函数。生成器的环境(绑定的变量)会在每次执行后被保存,下次进入时可继续使用。

yield

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

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://www.ucloud.cn/yun/82224.html

相关文章

  • 使用TypeScript开发微信小程序

    摘要:使用开发微信小程序基础接口核心设计原则之一就是类型检查,通过使用接口可以进行类型检查,满足传统面向对象思想,利于有效开发,有效避免类型转换问题。使用开发微信小程序基础迭代器为每一个对象定义了默认的迭代器。 使用TypeScript开发微信小程序(1)——基础:数据类型(Type) ​TypeScript 的基本数据类型有boolean、number、string 、array、enum...

    xingpingz 评论0 收藏0
  • TS下的装饰者模式(Decorator)

    摘要:装饰者模式装饰者模式就是动态的给类或对象增加功能的设计模式。下的实现里的装饰器目前处在建议征集的第二阶段,不被浏览器所支持,如果想要提前使用这个新特性就需要,等工具进行转译。这里介绍下的用法。 1.1、装饰者模式 装饰者模式就是动态的给类或对象增加功能的设计模式。在程序运行时动态的给一个具备基础功能的类或对象添加新的功能,并且不会改变会破坏基础类和对象的功能。先提炼出产品的最小可用产品...

    SolomonXie 评论0 收藏0
  • 【译】关于转译 JavaScript 程序员需要知道的

    摘要:他们的计划是,使用微软开发者们所习惯的其他语言的开发工具所支持的静态类型,得到更好的代码。在微软内部,被和以及团队所使用,而且它被系的等公司使用。标准的编辑,同时也是微软项目高级经理的也同意。 本文转载自:众成翻译译者:文蔺链接:http://www.zcfy.cc/article/895原文:http://thenewstack.io/javascript-transpilers-n...

    freecode 评论0 收藏0
  • ESLint 在中大型团队的应用实践

    摘要:自动化接入和升级方案通过命令行工具提供一键接入升级能力,同时集成到团队脚手架中,大大降低了工程接入和维护的成本。原始代码经过解析器的解析,在管道中逐一经过所有规则的检查,最终检测出所有不符合规范的代码,并输出为报告。 引言 代码规范是软件开发领域经久不衰的话题,几乎所有工程师在开发过程中都会遇到,并或多或少会思考过这一问题。随着前端应用的大型化和复杂化,越来越多的前端工程师和团队开始重...

    alogy 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<