当前位置: 首页 > 科技观察

JS对象遍历你了解多少?

时间:2023-03-12 02:13:53 科技观察

文章开头主要总结了JS对象的7种遍历方式(不包括数组、Map、Set结构)。写这篇文章的那天,正好是我最喜欢的球星艾弗森45岁生日,所以本文将以艾弗森的基本信息为模板,生成一个JS对象并进行遍历。定义对象首先让我们定义对象player,如下面的代码所示:constplayer={name:'AllenIverson',[Symbol('birthday')]:'1975/06/07',};Object.defineProperties(player,{isHallofFame:{enumerable:false,value:true,},[Symbol('ScoreKingTime')]:{enumerable:false,value:4,},});Object.defineProperties(player.__proto__,{university:{enumerable:true,value:'Georgetown',},team:{enumerable:false,value:'76ers',},[Symbol('country')]:{enumerable:true,value:'USA',},[符号('家乡')]:{enumerable:false,value:'弗吉尼亚',},});如上代码所示,定义了一个player对象,它有以下8个属性:通过控制台输出也比较方便直观:浅色的属性是不可枚举的属性,__proto__下的属性是其原型上的属性(即Object.prototype)。Symbol类型的值自然是Symbol属性for...inMDN:for...in语句迭代对象的所有可枚举属性,这些属性由字符串作为键(忽略由Symbols键的),包括继承的可枚举属性。for(constnameinplayer){console.log('name:',name);}//name:name//name:universityfor...in循环是我们比较常用的遍历对象的方法。结合MDN中的说法和输出结果,不难得到它的可遍历属性,包括自身和原型属性上的所有可枚举对象,不包括Sy因为mbol属性可以遍历到原型上的可枚举属性,所以我们的代码中通常会多一句(如果我们不需要原型上的属性):for(constnameinplayer){if(Object.prototype.hasOwnProperty.call(player,name)){console.log('name:',name);}}//name:nameObject.keysMDN:Object.keys()方法返回给定对象自身可枚举属性名的数组,迭代与普通循环的顺序相同.constkeys=Object.keys(player);console.log('keys:',keys);//keys:["name"]Object.keys可能是我们最常用遍历的方法,比如Vue源码中对数据的遍历和响应式处理,也是用到了这种方法。输出还显示它返回了它自己的所有可枚举属性(不包括Symbol属性),并且不包含原型上的任何属性。Object.getOwnPropertyNamesMDN:Object.getOwnPropertyNames()方法返回直接在给定对象中找到的所有属性(包括不可枚举的属性,但使用Symbol的属性除外)的数组。constownPropertyNames=Object.getOwnPropertyNames(player.log)'ownPropertyNames:',ownPropertyNames);//ownPropertyNames:["name","isHallofFame"]Object.getOwnPropertyNames返回其自身的所有属性(包括不可枚举的属性但不包括Symbol属性),不包括原型上的任何属性Attributes。Object.getOwnPropertySymbolsMDN:Object.getOwnPropertySymbols()方法返回直接在给定对象上找到的所有符号属性的数组。onstownPropertySymbols=Object.getOwnPropertySymbols(player);console.log('ownPropertySymbols:',ownPropertySymbols);//ownPropertySymbols:[Symbol(birthday),Symbol(ScoreKingTime)]通过输出不难看出Object.getOwnPropertySymbols返回的是自身所有的Symbol属性(包括不可枚举的),但不包含原型上的任何属性。Reflect.ownKeysMDN:静态Reflect.ownKeys()方法返回目标对象自身属性keys的数组。constownKeys=Reflect.ownKeys(player);console.log('ownKeys:',ownKeys)//ownKeys:["name","isHallofFame",Symbol(birthday),Symbol(ScoreKingTime)]Reflect.ownKeys返回自身的所有属性(包括不可枚举和所有Symbol属性),不包括原型上的任何属性。Object.valuesMDN:Object.values()方法返回给定对象自身可枚举属性值的数组,其顺序与for...in循环提供的顺序相同。(唯一的区别是for...in循环也枚举原型链中的属性。)constvalues=Object.values(player);console.log('values:',values);//values:["AllenIverson"]Object.values和Object.keys一样,它遍历了自己所有的可枚举属性(不包括Symbol属性),不包括原型上的任何属性。但与Object.keys不同的是,它返回的不再是一个键值,而是一个值集合。Object.entriesMDN:Object.entries()方法返回给定对象自己的可枚举字符串键控属性[key,value]对的数组,其顺序与for...in循环提供的顺序相同。(唯一重要的区别是for...in循环也枚举原型链中的属性)。consentries=Object.entries(player);console.log('entries:',entries);//entries:[["name","AllenIverson"]]也和Object.keys一样,它遍历了自己所有的可枚举属性(不包括Symbol属性),不包括原型上的任何属性。不同的是它的返回值是[key,value]的集合。Object.entries在我们平时的开发中可能很少用到,但是可以和Object.fromEntries一起使用:如下代码://objectconversionconstobject1={a:1,b:2,c:3};constobject2=Object.fromEntries(Object.entries(object1).map(([key,val])=>[key,val*2]));console.log(object2);//{a:2,b:4,c:6}总结结合文章中的代码输出结果,可以得到下表:简而言之:只有for...in可以遍历到原型上的属性Object.getOwnPropertyNames和Reflect.ownKeys可以获得不可枚举属性Object.getOwnPropertySymbols和Reflect.ownKeys可以获取Symbol属性