for ....of和迭代器相关知识点

学习自大神 https://www.cnblogs.com/ghostwu/p/7587498.html

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

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

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

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

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

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

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

let userList = [ 'ghostwu', '悟空', '八戒' ];
let iterator = userList[Symbol.iterator]();
console.log( iterator.next() ); //{ value : 'ghostwu', done : false }
console.log( iterator.next() ); //{ value : '悟空', done : false }
console.log( iterator.next() ); //{ value : '八戒', done : false }
console.log( iterator.next() ); //{ value : undefined, done : false 
 

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

function isIterable( obj ){
    return typeof obj[Symbol.iterator] === 'function';
}
console.log( isIterable( [ 10, 20 ,30 ] ) ); //true
console.log( isIterable( "ghostwu" ) ); //true
console.log( isIterable( new Map() ) ); //true
console.log( isIterable( new Set() ) ); //true
console.log( isIterable( new Object() ) ); //false
console.log( isIterable( {} ) );//false

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

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

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

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

let obj = {
    items : [],
    *[Symbol.iterator](){
        for( let item of this.items ) {
            yield item;
        }
    }
}
obj.items.push( 10 );
obj.items.push( 20 );
obj.items.push( 30 );
var iterator = obj[Symbol.iterator]();
console.log( iterator.next() ); //{ value : 10, done: false }
console.log( iterator.next() ); //{ value : 20, done : false }
console.log( iterator.next() ); //{ value : 30, done : false }
console.log( iterator.next() ); //{ value : undefined, done : true }

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

let obj = {
    items : [],
    *[Symbol.iterator](){
        for( let item of this.items ) {
            yield item;
        }
    }
}
obj.items.push( 10 );
obj.items.push( 20 );
obj.items.push( 30 );

for ( let val of obj ) {
    console.log( val );
}

内置迭代器:

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

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

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

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

let userList = [ 'ghostwu', '悟空', '八戒' ];

for ( let name of userList.entries() ) {
    console.log( name );
}

let set = new Set( [ 10, 20, 30 ] );
for ( let num of set.entries() ){
    console.log( num );
}

let map = new Map( [ [ 'name', 'ghostwu' ], [ 'age', 22 ] ] );
for ( let detail of map.entries() ){
    console.log( detail );
}

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

let set = new Set( [ 10, 20, 30 ] );
for ( let num of set.values() ){
    console.log( num );
}

let map = new Map( [ [ 'name', 'ghostwu' ], [ 'age', 22 ] ] );
for ( let detail of map.values() ){
    console.log( detail );
}

let set = new Set( [ 10, 20, 30 ] );
for ( let num of set.keys() ){
    console.log( num );
}

let map = new Map( [ [ 'name', 'ghostwu' ], [ 'age', 22 ] ] );
for ( let detail of map.keys() ){
    console.log( detail );
}

 默认的迭代器:

let userList = [ 'ghostwu', '悟空', '八戒' ];

//相当于调用values
for ( let name of userList ) {
    console.log( name );
}

let set = new Set( [ 10, 20, 30 ] );
//相当于调用values
for ( let num of set ){
    console.log( num );
}

let map = new Map( [ [ 'name', 'ghostwu' ], [ 'age', 22 ] ] );
//相当于调用entries
for ( let detail of map ){
    console.log( detail );
}

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

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

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

let set = new Set( [ 10, 20, 30 ] );
let arr = [...set];
console.log( arr ); // [10,20,30]

let map = new Map( [ [ 'name', 'ghostwu' ], [ 'age', 22 ] ]);
console.log( [...map] ); // [ [ 'name', 'ghostwu' ], [ 'age', 22 ] ]

let arr1 = [ 10, 20, 30 ];
let arr2 = [ 'ghostwu', '八戒', '悟空' ];
let combine = [ ...arr1, ...arr2, 'done' ];
console.log( combine ); // [10, 20, 30, "ghostwu", "八戒", "悟空", "done"]

 

  • 24
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 21
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值