对于常常应用对象的咱们,在有些业务场景下须要对对象的属性进行遍历,上面我总结了几种罕用的 JS 遍历对象属性的办法。
太长不看版:
JS 遍历对象的次要办法有 for...in
、Object.keys()
、Object.getOwnPropertyNames()
、Object.getOwnPropertySymbols()
、Reflect.ownKeys()
。
备注:可枚举:属性的 enumerable 值为 true;本身属性:自有的,不是从原型上继承来的属性。
- 遍历对象所有的可枚举属性(自有的+继承的属性),应用 for...in
- 遍历对象自有的所有可枚举属性(非继承属性),应用 Object.keys() 或 for...in + Objec.hasOwnProperty()
- 获取对象所有继承属性(非自有属性),能够应用 for...in + Object.keys()
- 遍历对象自有的所有可枚举和不可枚举属性(非继承属性),应用 Object.getOwnPropertyNames()
- 获取对象自有的所有可枚举、不可枚举属性和继承属性,应用 for...in + Object.getOwnPropertyNames(obj) 或 for...in + Object.keys() + Object.getOwnPropertyNames(obj)
如果想理解更多具体内容,请往下看:
一、for...in
for...in
用于以任意程序遍历对象所有的可枚举属性(包含对象本身的和继承的可枚举属性,不含 Symbol 属性)。
let obj = { name: 'Scarlett', age: 37, [Symbol()]: 'Johansson'}for (let key in obj) { console.log(key) // name age}// 在原型上增加一个可枚举属性Object.prototype.nationality = 'America'// 在obj对象上增加一个不可枚举属性Object.defineProperty(obj, 'occupation', { value: 'actress', enumerable: false})for (let key in obj) { console.log(key, obj[key])}/* 输入后果:蕴含对象本身的可枚举属性和原型上的可枚举属性name Scarlettage 37nationality America*/
想必大家对这个语法并不生疏,但在理论的业务场景中是对属性的精准应用,而不是间接这样用。
咱们晓得对象具备的属性可能是多起源的,可能是本身创立的,可能继承自原型,也可能继承自构造函数......其中咱们能够通过 Object.hasOwnProperty()
来判断这个属性是否是自有属性,该办法会过滤掉那些继承来的属性。
for...in
循环能够拜访到对象具备的所有可枚举属性,而对象的不可枚举属性则是由属性的 enumerable 值决定的,比方 constructor,length 属性等都不能被 for...in 拜访到。办法 Object.propertyIsEnumerable()
能够判断此对象是否蕴含某个属性,并且这个属性是否可枚举(通过原型继承的属性除外)。
二、for...of
for...of
是 ES6 新增的遍历形式,它为不同的数据结构提供了对立的遍历机制。任何数据结构只有实现了 Iterator 接口的,都能够被遍历。对于 Iterator 接口能够参考 这里
for...of
循环能够应用的范畴包含 Array、Set 和 Map 构造、类数组对象(比方arguments 对象、DOM NodeList 对象)、字符串等。
1.类数组对象
以下是 for...of 循环字符串、arguments 对象、DOM 元素汇合的例子:
// 字符串let str = "hello";for (let s of str) { console.log(s); // h e l l o}// DOM元素汇合let domList = document.querySelectorAll("p");for (let p of domList) { p.classList.add("test");}// arguments对象function printArgs() { for (let arg of arguments) { console.log(arg); }}printArgs('a', 'b'); // 'a' 'b'
尽管不是所有的类数组对象都具备 Iterator 接口,但一个简便的解决办法,就是应用 Array.from()
办法将一个相似数组或可迭代对象转为一个浅拷贝的数组实例。
let arrayLike = { length: 2, 0: 'a', 1: 'b' };// 报错 TypeError: arrayLike is not iterablefor (let key of arrayLike) { console.log(key);}// 正确执行for (let key of Array.from(arrayLike)) { console.log(key); // 'a' 'b'}
2.一般对象
对于一般的对象,for...of 构造不能间接应用,会报错,必须部署了 Iterator 接口后能力应用。
let obj = { name: 'Scarlett', age: 37}// 报错 TypeError: obj is not iterablefor (let key of obj) { console.log(key);}// 解决:应用Object.keys()办法将对象的键名生成一个数组,而后遍历。for (var key of Object.keys(obj)) { console.log(key);}
三、Object.keys()
Object.keys()
ES5 新增的一个对象办法,该办法接管一个对象为参数,返回一个数组,蕴含该对象自有的可枚举属性(不含继承的和Symbol属性),数组中属性名的排列程序和失常循环遍历该对象时返回的程序统一 。
let obj = { name: 'Scarlett', age: 37, [Symbol()]: 'Johansson'}// 在原型上增加一个可枚举属性Object.prototype.nationality = 'America'// 在obj对象上增加一个不可枚举属性Object.defineProperty(obj, 'occupation', { value: 'actress', enumerable: false})// 获取对象自有的可枚举属性Object.keys(obj).map(key => { console.log(key); // name age})console.log(Object.entries(obj)); // [["name", "Scarlett"], ["age", 37]]console.log(Object.values(obj)); // ["Scarlett", 37]
留神:该办法如果参数不是一个对象,将被强制转换为一个对象。
依据后面的办法的特点,应用 for...in
联合 Object.hasOwnProperty()
也能达到获取本身的可枚举属性或继承属性的目标。
// 失去所有可枚举属性(自有的和继承的属性)for (let key in obj) { // 过滤掉继承属性 if (obj.hasOwnProperty(key)) { console.log(key); }}
另外:
Object.entries()
返回指定对象本身的可枚举属性的键值对(不含继承的和Symbol属性)数组;Object.values()
返回指定对象本身的所有可枚举属性的值(不含继承的和Symbol属性)组成的数组;
这两个办法的应用范畴和 Object.keys() 办法相似,这里不再具体阐明。
四、Object.getOwnPropertyNames()
Object.getOwnPropertyNames()
办法接管一个对象为参数,返回该对象所有可枚举和不可枚举属性的属性名(不含Symbol属性)组成的数组。
// 接上democonsole.log(Object.getOwnPropertyNames(obj)); // ["name", "age", "occupation"]
综上,能够拓展出 for...in
联合 Object.getOwnPropertyNames()
获取对象自有的所有可枚举、不可枚举属性和继承属性。
const getAllPropertyNames = (obj) => { let props = Object.assign([], Object.getOwnPropertyNames(obj)) // 失去所有的可枚举属性(自有的和继承的属性) for (let key in obj) { // 过滤自有的不可枚举属性 if (!Object.getOwnPropertyNames(obj).includes(key)) { props.push(key) } } return props;};getAllPropertyNames(obj); // ["name", "age", "occupation", "nationality"]
这里也能够应用 for...in
+ Object.keys()
+ Object.getOwnPropertyNames(obj)
的办法失去同样的后果,有趣味的能够自行尝试。
五、Object.getOwnPropertySymbols()
Object.getOwnPropertySymbols()
办法返回指定对象本身所有的Symbol属性的数组。
// 接上demolet symbolsArr = Object.getOwnPropertySymbols(obj);for( let sym of symbolsArr){ console.log(sym, obj[sym]); // Symbol() "Johansson"}// 给对象增加一个不可枚举的Symbol属性Object.defineProperties(obj, { [Symbol('aa')]: { value: 'localSymbol', enumerable: false }})Object.getOwnPropertySymbols(obj).map(key => { console.log(key, obj[key]); // Symbol() "Johansson", Symbol(aa) "localSymbol"})
六、Reflect.ownKeys()
Reflect.ownKeys()
返回指定对象本身的所有属性(蕴含不可枚举属性和Symbol属性)组成的数组。它的返回值等同于Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target))
。
// 接上demoReflect.ownKeys(obj).map(key => { console.log(key, obj[key])})/* 输入后果:name Scarlettage 37occupation actressSymbol() "Johansson"*/
以上,
对于对象的更多用法,请移步 Mozilla MDN