前言
对象的每个属性都有一个描述对象(Descriptor),用来控制该属性的行为。Object.getOwnPropertyDescriptor()方法返回指定对象上一个自有属性对应的属性描述符。(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性)
通过字面量方式创建一个对象obj,并获取其自有属性foo的属性描述符。代码如下所示:
let obj = { foo: 123 };
Object.getOwnPropertyDescriptor(obj, 'foo');
显示结果如下图所示:
描述对象Descriptor的enumerable属性,称为“可枚举性”,如果该属性为false,就表示不可枚举,即某些操作会忽略当前属性。
var obj = { foo: 123 };
Object.getOwnPropertyDescriptor(obj, 'foo').enumerable;
显示结果如下图所示:
在遍历一个对象的属性时,通常根据属性是否可枚举这个标准来进行。目前有四种方法仅对可枚举的属性进行遍历,分别为:
- for…in;
- Object.keys();
- JSON.stringify();
- Object.assign()【ES6新增】
对需要学习遍历对象可枚举属性的以上四种方法的同学,几种遍历一个对象包含的可枚举属性的方法详解 一文可以帮你答疑解惑。故本文仅介绍可以遍历对象所有属性的方法,也就是对属性的可枚举性和不可枚举性不做限制的方法进行介绍。
一、Object.getOwnPropertyNames(obj)【不遍历Symbol属性】
Object.getOwnPropertyNames()方法返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组。数组中枚举属性的顺序与通过 for…in 循环(或 Object.keys)迭代该对象属性时一致。数组中不可枚举属性的顺序未定义。
案例一
var obj = {
name: 'aaa',
age: 'bbb',
say: 'ccc',
[Symbol("id")]: 'ddd' //设置Symbol属性
}
Object.defineProperty(obj, 'say', { //设置obj对象的say不可枚举
enumerable: false
});
Object.getOwnPropertyNames(obj).forEach(function(key){
console.log(key+"\t\t\t\t"+key+".enumerable="+Object.getOwnPropertyDescriptor(obj, key).enumerable+"\t\t\t\t"+'result='+obj[key]);
});
显示结果如下图所示:
案例二
对Object对象的所有属性进行遍历:
Object.getOwnPropertyNames(Object).forEach(function(key){
getStrLen(key);
console.log(key+str+key+".enumerable="+Object.getOwnPropertyDescriptor(Object, key).enumerable+str+'result='+Object[key]);
});
//计算key的长度和应该添加的tab个数
var str = "";//tab字符串
function getStrLen(key){
let bitNum = 3;//属性字符串每3位输出一个tab键
let maxLen = 25;//属性字符串的最大长度为25
let num = Math.ceil(key.length/bitNum);
let p = Math.ceil(maxLen/bitNum+1);
str = "";
for(let i = p; i > num; i--){
str += "\t";
}
}
显示结果如下图所示:
由上图可知:Object对象的所有属性均为不可枚举类型。
二、Reflect.ownKeys(obj)【遍历Symbol属性】
静态方法 Reflect.ownKeys() 返回一个由目标对象自身的属性键组成的数组。其返回值是由目标对象的自身属性键组成的 Array。 即其返回值等同于Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target)),也就是说Reflect.ownKeys(obj)的返回值是在Object.getOwnPropertyNames(target)返回值与symbol类型的值之和。
案例一
var obj = {
name: 'aaa',
age: 'bbb',
say: 'ccc',
[Symbol("id")]: 'ddd' //设置Symbol属性
}
Object.defineProperty(obj, 'say', { //设置obj对象的say不可枚举
enumerable: false
});
console.log(Reflect.ownKeys(obj));
Reflect.ownKeys(obj).forEach(function(key){
if(typeof key == "symbol"){
console.log("----------------------我是Symbol类型,不参与运算-------------------------");
console.log(key);
}else{
console.log(key+"\t\t\t\t"+key+".enumerable="+Object.getOwnPropertyDescriptor(obj, key).enumerable+"\t\t\t\t"+'result='+obj[key]);
}
});
显示结果如下图所示:
案例二
Reflect.ownKeys(Object).forEach(function(key){
getStrLen(key);
console.log(parseInt(keyNum)+"、"+key+str+key+".enumerable="+Object.getOwnPropertyDescriptor(Object, key).enumerable+str+'result='+Object[key]);
});
//计算key的长度和应该添加的tab个数
var str = "";//tab字符串
var keyNum = 0;//记忆当前属性的输出次序
function getStrLen(key){
let bitNum = 3;//属性字符串每3位输出一个tab键
let maxLen = 25;//属性字符串的最大长度为25
let num = Math.ceil(key.length/bitNum);
let p = Math.ceil(maxLen/bitNum+1);
str = "";
for(let i = p; i > num; i--){
str += "\t";
}
keyNum++;
}
显示结果如下图所示:
对于不包含symbol类型属性的对象来说,Reflect.ownKeys(obj)的返回值与Object.getOwnPropertyNames(obj)相同。
好啦,关于JavaScript获取一个对象所有属性(可枚举属性和不可枚举属性)的所有方法都整理在这里啦,希望能帮到各位!若有考虑不周之处,还望指正!