[js高手之路] es6系列教程 - 迭代器,生成器,for...of,entries,values,keys等详解

接着上文[js高手之路] es6系列教程 - 迭代器与生成器详解继续.

在es6中引入了一个新的循环结构for ....of, 主要是用来循环可迭代的对象,那么什么是可迭代的对象呢?

可迭代的对象一般都有Symbol.iterator属性,你可以在控制台中用console.dir打印数组,Map,Set,在他们的原型对象(prototype)上面就能找到。这个属性与迭代器密切相关,通过该函数可以返回一个迭代器,下文,我会举一个例子。一般来说所有的集合对象(数组,Set,Map 以及字符串)都是可迭代的对象。这些对象中都有默认的迭代器.

for..of循环的遍历原理:

循环每执行一次都会调用可迭代对象的next()方法, 并将迭代器返回的结果对象的value属性存储在一个变量中,循环将持续执行这一过程,直到done返回true

1 let values = [ 10, 20, 30 ];
2 for( let val of values ) {
3     console.log( val );
4 }

这段for...of循环的代码通过调用values数组的Symbol.iterator方法来获取迭代器, 这一步是由js引擎自动完成的,随后迭代器的next()方法被多次调用,返回对象的value值并存储在变量val中,依次为: 10, 20, 30,done为true的时候退出,最后 不会把undefined赋值给val.

利用Symbol.iterator访问默认的迭代器

1 let userList = [ ‘ghostwu‘, ‘悟空‘, ‘八戒‘ ];
2 let iterator = userList[Symbol.iterator]();
3 console.log( iterator.next() ); //{ value : ‘ghostwu‘, done : false }
4 console.log( iterator.next() ); //{ value : ‘悟空‘, done : false }
5 console.log( iterator.next() ); //{ value : ‘八戒‘, done : false }
6 console.log( iterator.next() ); //{ value : undefined, done : false }

由于具有Symbol.iterator属性的对象都有默认的迭代器,这个特性可以用来检测对象是否为可迭代对象.

1 function isIterable( obj ){
2     return typeof obj[Symbol.iterator] === ‘function‘;
3 }
4 console.log( isIterable( [ 10, 20 ,30 ] ) ); //true
5 console.log( isIterable( "ghostwu" ) ); //true
6 console.log( isIterable( new Map() ) ); //true
7 console.log( isIterable( new Set() ) ); //true
8 console.log( isIterable( new Object() ) ); //false
9 console.log( isIterable( {} ) );//false

所以,for..of不能遍历对象( json )

var obj = {
    name : ‘ghostwu‘,
    age : 22,
    sex : ‘man‘
};
for( var val of obj ) {
    console.log( val );
}

上面这种遍历方式,就会报错.

但是,我们可以为对象增加一个迭代器方法

 1 let obj = {
 2     items : [],
 3     *[Symbol.iterator](){
 4         for( let item of this.items ) {
 5             yield item;
 6         }
 7     }
 8 }
 9 obj.items.push( 10 );
10 obj.items.push( 20 );
11 obj.items.push( 30 );
12 var iterator = obj[Symbol.iterator]();
13 console.log( iterator.next() ); //{ value : 10, done: false }
14 console.log( iterator.next() ); //{ value : 20, done : false }
15 console.log( iterator.next() ); //{ value : 30, done : false }
16 console.log( iterator.next() ); //{ value : undefined, done : true }

给Symbol.iterator属性添加一个生成器,那么对象就具备迭代器的功能了,那么就能够使用for...of方法了

 1 let obj = {
 2     items : [],
 3     *[Symbol.iterator](){
 4         for( let item of this.items ) {
 5             yield item;
 6         }
 7     }
 8 }
 9 obj.items.push( 10 );
10 obj.items.push( 20 );
11 obj.items.push( 30 );
12
13 for ( let val of obj ) {
14     console.log( val );
15 }

内置迭代器:

可迭代的对象,都内置以下3种迭代器

entries(): 返回一个迭代器,值为键值对

values(): 返回一个迭代器, 值为集合的值

keys(): 返回一个迭代器,值为集合中的所有键

 1 let userList = [ ‘ghostwu‘, ‘悟空‘, ‘八戒‘ ];
 2
 3 for ( let name of userList.entries() ) {
 4     console.log( name );
 5 }
 6
 7 let set = new Set( [ 10, 20, 30 ] );
 8 for ( let num of set.entries() ){
 9     console.log( num );
10 }
11
12 let map = new Map( [ [ ‘name‘, ‘ghostwu‘ ], [ ‘age‘, 22 ] ] );
13 for ( let detail of map.entries() ){
14     console.log( detail );
15 }

entries返回的是键值对,注意Set集合,返回的键和值是一样的.

1 let set = new Set( [ 10, 20, 30 ] );
2 for ( let num of set.values() ){
3     console.log( num );
4 }
5
6 let map = new Map( [ [ ‘name‘, ‘ghostwu‘ ], [ ‘age‘, 22 ] ] );
7 for ( let detail of map.values() ){
8     console.log( detail );
9 }

1 let set = new Set( [ 10, 20, 30 ] );
2 for ( let num of set.keys() ){
3     console.log( num );
4 }
5
6 let map = new Map( [ [ ‘name‘, ‘ghostwu‘ ], [ ‘age‘, 22 ] ] );
7 for ( let detail of map.keys() ){
8     console.log( detail );
9 }

 默认的迭代器:

 1 let userList = [ ‘ghostwu‘, ‘悟空‘, ‘八戒‘ ];
 2
 3 //相当于调用values
 4 for ( let name of userList ) {
 5     console.log( name );
 6 }
 7
 8 let set = new Set( [ 10, 20, 30 ] );
 9 //相当于调用values
10 for ( let num of set ){
11     console.log( num );
12 }
13
14 let map = new Map( [ [ ‘name‘, ‘ghostwu‘ ], [ ‘age‘, 22 ] ] );
15 //相当于调用entries
16 for ( let detail of map ){
17     console.log( detail );
18 }

Map的默认行为,可以用解构来简写:

1 let map = new Map( [ [ ‘name‘, ‘ghostwu‘ ], [ ‘age‘, 22 ] ] );
2 for ( let [ key, value ] of map ) {
3     console.log( key  + ‘--->‘ + value );
4 }

利用展开运算符把Set与Map转化成数组

 1 let set = new Set( [ 10, 20, 30 ] );
 2 let arr = [...set];
 3 console.log( arr ); // [10,20,30]
 4
 5 let map = new Map( [ [ ‘name‘, ‘ghostwu‘ ], [ ‘age‘, 22 ] ]);
 6 console.log( [...map] ); // [ [ ‘name‘, ‘ghostwu‘ ], [ ‘age‘, 22 ] ]
 7
 8 let arr1 = [ 10, 20, 30 ];
 9 let arr2 = [ ‘ghostwu‘, ‘八戒‘, ‘悟空‘ ];
10 let combine = [ ...arr1, ...arr2, ‘done‘ ];
11 console.log( combine ); // [10, 20, 30, "ghostwu", "八戒", "悟空", "done"]
时间: 2024-10-20 06:03:04

[js高手之路] es6系列教程 - 迭代器,生成器,for...of,entries,values,keys等详解的相关文章

[js高手之路] es6系列教程 - 迭代器与生成器详解

什么是迭代器? 迭代器是一种特殊对象,这种对象具有以下特点: 1,所有对象都有一个next方法 2,每次调用next方法,都会返回一个对象,该对象包含两个属性,一个是value, 表示下一个将要返回的值.另一个是done,他是一个布尔值,用来表示该迭代器是否还有数据可以返回. 3,迭代器还会保存一个内部指针指向当前集合中的值 设计模式中有个迭代模式,跟迭代器是差不多的,我之前有写过2篇文章关于迭代模式: [js高手之路] 设计模式系列课程 - 迭代器(1) [js高手之路] 设计模式系列课程 -

[js高手之路] es6系列教程 - promise常见用法详解(resolve,reject,catch,then,all,race)

关于promise我在之前的文章已经应用过好几次,如[js高手之路]Node.js+jade+express+mongodb+mongoose+promise实现todolist,本文就来讲解下promise的常见用法. 为什么会有promise,他的作用是什么? promise主要是为了解决js中多个异步回调难以维护和控制的问题. 什么是promise? 从图中,我们可以看出,Promise是一个函数,这个函数上有在项目中常用的静态方法:all, race, reject,resolve等,原

[js高手之路] es6系列教程 - new.target属性与es5改造es6的类语法

es5的构造函数前面如果不用new调用,this指向window,对象的属性就得不到值了,所以以前我们都要在构造函数中通过判断this是否使用了new关键字来确保普通的函数调用方式都能让对象复制到属性 1 function Person( uName ){ 2 if ( this instanceof Person ) { 3 this.userName = uName; 4 }else { 5 return new Person( uName ); 6 } 7 } 8 Person.proto

[js高手之路] es6系列教程 - var, let, const详解

function show( flag ){             console.log( a );             if( flag ){                 var a = 'ghostwu';                 return a;             } else {                 console.log( a );                 return null;             }         } 我们从e

[js高手之路] es6系列教程 - Map详解以及常用api

ECMAScript 6中的Map类型是一种存储着许多键值对的有序列表.键值对支持所有的数据类型. 键 0 和 ‘0’会被当做两个不同的键,不会发生强制类型转换. 如何使用Map? let map = new Map(); 常用方法: set( 键,值 ):  添加新的键值对元素 get( 键 ): 获取键对应的值,如果这个值不存在,返回undefined 1 let map = new Map(); 2 map.set( '0', 'ghostwu' ); 3 map.set( 0, 'gho

[js高手之路]设计模式系列课程-发布者,订阅者重构购物车

发布者订阅者模式,是一种很常见的模式,比如: 一.买卖房子 生活中的买房,卖房,中介就构成了一个发布订阅者模式,买房的人,一般需要的是房源,价格,使用面积等信息,他充当了订阅者的角色 中介拿到卖主的房源信息,根据手头上掌握的客户联系信息(买房的人的手机号),通知买房的人,他充当了发布者的角色 卖主想卖掉自己的房子,就需要告诉中介,把信息交给中介发布 二,网站订阅信息的用户 订阅者角色:需要订阅某类信息的网民,如某个网站的javascript类型文章 发布者角色:邮箱服务器,根据网站收集到的用户订

[js高手之路]深入浅出webpack教程系列9-打包图片(file-loader)用法

[js高手之路]深入浅出webpack教程系列索引目录: [js高手之路]深入浅出webpack教程系列1-安装与基本打包用法和命令参数 [js高手之路]深入浅出webpack教程系列2-配置文件webpack.config.js详解(上) [js高手之路]深入浅出webpack教程系列3-配置文件webpack.config.js详解(下) [js高手之路]深入浅出webpack教程系列4-插件使用之html-webpack-plugin配置(上) [js高手之路]深入浅出webpack教程系

[js高手之路]设计模式系列课程-组合模式+寄生组合继承实战新闻列表

所谓组合模式,就是把一堆结构分解出来,组成在一起,现实中很多这样的例子,如: 1.肯德基套餐就是一种组合模式, 比如鸡腿堡套餐,一般是是由一个鸡腿堡,一包薯条,一杯可乐等组成的 2.组装的台式机同理,由主板,电源,内存条,显卡, 机箱,显示器,外设等组成的 把一个成型的产品组成部件,分成一个个独立的部件,这种方式可以做出很多灵活的产品,这就是组合模式的优势 比如:家用台式机电脑,要求配置比较低, 这个时候只需要主板+电源+内存条+机箱+显示器+外设就可以了,不需要配置独立显卡 鸡腿堡+鸡翅+紫薯

[js高手之路]深入浅出webpack教程系列7-( babel-loader,css-loader,style-loader)的用法

什么是loader呢,官方解释为文件的预处理器,通俗点说webpack在处理静态资源的时候,需要加载各种loader,比如,html文件,要用html-loader, css文件要用css-loader,style-loader等等. 官方参考文档:https://webpack.js.org/loaders/ 我们从本文开始,重新搭建一个项目结构来解释下loader的用法. 一.项目结构搭建准备: 目录结构: 1 demo3 2 dist 3 src 4 components 5 modal.