当前位置: 首页 > news >正文

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 系列接口要方便快捷的多。

相关文章:

  • thinkphp如何省略index.php
  • 安卓开源项目周报0329
  • 2018(2017)美图java服务端笔试(回忆录)
  • 2016蓝桥杯 煤球数目 (代码)
  • React-Native PanResponder手势识别器
  • DNS的搭建
  • P3-SQL 学习笔记
  • SANS:2017年网络威胁情报现状调研报告
  • 当 Node.js 遇见 Docker
  • Centos 7.0变动记录贴(持续记录)
  • vue脚手架vue-cli
  • 漫谈《大型网站技术架构》
  • SDN的概念和价值
  • jQuery.extend()参数
  • [LeetCode]Spiral Matrix
  • @jsonView过滤属性
  • 【5+】跨webview多页面 触发事件(二)
  • Apache Pulsar 2.1 重磅发布
  • java8 Stream Pipelines 浅析
  • node-glob通配符
  • vue自定义指令实现v-tap插件
  • 服务器之间,相同帐号,实现免密钥登录
  • 缓存与缓冲
  • 如何用Ubuntu和Xen来设置Kubernetes?
  • 译有关态射的一切
  • 原生Ajax
  • mysql 慢查询分析工具:pt-query-digest 在mac 上的安装使用 ...
  • ​MySQL主从复制一致性检测
  • #stm32整理(一)flash读写
  • #我与虚拟机的故事#连载20:周志明虚拟机第 3 版:到底值不值得买?
  • (10)ATF MMU转换表
  • (20050108)又读《平凡的世界》
  • (Java数据结构)ArrayList
  • (Matalb时序预测)PSO-BP粒子群算法优化BP神经网络的多维时序回归预测
  • (Redis使用系列) SpirngBoot中关于Redis的值的各种方式的存储与取出 三
  • (八十八)VFL语言初步 - 实现布局
  • (非本人原创)我们工作到底是为了什么?​——HP大中华区总裁孙振耀退休感言(r4笔记第60天)...
  • (附源码)ssm教材管理系统 毕业设计 011229
  • (南京观海微电子)——I3C协议介绍
  • (十七)Flask之大型项目目录结构示例【二扣蓝图】
  • (一)RocketMQ初步认识
  • (转)3D模板阴影原理
  • (转)拼包函数及网络封包的异常处理(含代码)
  • ./和../以及/和~之间的区别
  • .class文件转换.java_从一个class文件深入理解Java字节码结构
  • .net core 连接数据库,通过数据库生成Modell
  • .Net Core缓存组件(MemoryCache)源码解析
  • .net mvc actionresult 返回字符串_.NET架构师知识普及
  • .NET 常见的偏门问题
  • .net和jar包windows服务部署
  • .NET文档生成工具ADB使用图文教程
  • .Net语言中的StringBuilder:入门到精通
  • .pub是什么文件_Rust 模块和文件 - 「译」
  • /bin/rm: 参数列表过长"的解决办法
  • /var/spool/postfix/maildrop 下有大量文件