准备
先来准备一个测试对象obj。
代码清单11
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30var notEnum = Symbol("继承不可枚举symbol");
var proto = {
[Symbol("继承可枚举symbol")]: "继承可枚举symbol",
name: "继承可枚举属性"
};
// 不可枚举属性
Object.defineProperty(proto, "age", {
value: "继承不可枚举属性"
});
// 不可枚举symbol属性
Object.defineProperty(proto, notEnum, {
value: "继承不可枚举symbol"
});
var obj = {
job1: "自有可枚举属性1",
job2: "自有可枚举属性2",
[Symbol("自有可枚举symbol")]: "自有可枚举symbol"
};
// 继承
Object.setPrototypeOf(obj, proto);
// 不可枚举属性
Object.defineProperty(obj, "address", {
value: "自有不可枚举属性"
});
// 不可枚举symbol属性
var ownNotEnum = Symbol("自有不可枚举symbol");
Object.defineProperty(obj, ownNotEnum, {
value: "自有不可枚举symbol"
});
五种武器
for…in
这个是对象遍历界的老兵了,通过这种方式可以遍历对象自身及继承的所有可枚举属性(不包括Symbol类型)。
代码清单21
2
3
4
5
6
7
8for(var attr in obj){
console.log(attr,"==",obj[attr]);
}
/*
job1 == 自有可枚举属性1
job2 == 自有可枚举属性2
name == 继承可枚举属性
*/
Object.keys
获取对象自身所有可枚举属性(不包括Symbol类型)组成的数组
代码清单31
2
3
4
5
6
7Object.keys(obj).map((attr)=>{
console.log(attr,"==",obj[attr]);
});
/*
job1 == 自有可枚举属性1
job2 == 自有可枚举属性2
*/
Object.getOwnPropertyNames
获取对象自身所有类型为非Symbol的属性名称(包括不可枚举)组成的数组
代码清单41
2
3
4
5
6
7
8Object.getOwnPropertyNames(obj).map((attr)=>{
console.log(attr,"==",obj[attr]);
});
/*
job1 == 自有可枚举属性1
job2 == 自有可枚举属性2
address == 自有不可枚举属性
*/
Object.getOwnPropertySymbols
获取对象自身所有类型为Symbol的属性名称(包括不可枚举)组成的数组
代码清单51
2
3
4
5
6
7Object.getOwnPropertySymbols(obj).map((attr)=>{
console.log(attr,"==",obj[attr]);
});
/*
Symbol(自有可枚举symbol) == 自有可枚举symbol
Symbol(自有不可枚举symbol) == 自有不可枚举symbol
*/
Reflect.ownKeys
获取一个对象的自身的所有(包括不可枚举的和Symbol类型)的属性名称组成的数组
代码清单61
2
3
4
5
6
7
8
9
10Reflect.ownKeys(obj).map((attr)=>{
console.log(attr,"==",obj[attr]);
});
/*
job1 == 自有可枚举属性1
job2 == 自有可枚举属性2
address == 自有不可枚举属性
Symbol(自有可枚举symbol) '==' '自有可枚举symbol'
Symbol(自有不可枚举symbol) '==' '自有不可枚举symbol'
*/
总结
武器库的说明书,根据需要选择合适的武器吧。
api | 操作 | 自身属性 | 不可枚举属性 | 继承属性 | Symbol属性 |
---|---|---|---|---|---|
for…in | 遍历 | yes | no | yes | no |
Object.keys | 返回属性数组 | yes | no | no | no |
Object.getOwnPropertyNames | 返回非Symbol属性数组 | yes | yes | no | no |
Object.getOwnPropertySymbols | 返回Symbol属性数组 | yes | yes | no | yes |
Reflect.ownKeys | 返回属性数组 | yes | yes | no | yes |
五种武器里最牛的就是Reflect.ownKeys
了,无论Symbol还是不可枚举通吃, 简直就是Object.getOwnPropertyNames
和Object.getOwnPropertySymbols
合体的效果。
扩展
Object.values
获取对象自身所有可枚举属性(不包括Symbol类型)的值组成的数组
代码清单71
2
3
4
5
6
7Object.values(obj).map((val)=>{
console.log(val);
});
/*
自有可枚举属性1
自有可枚举属性2
*/
Object.entries
获取对象自身所有可枚举属性(不包括Symbol类型)的键值对数组
代码清单71
2
3
4
5
6
7Object.entries(obj).map((val)=>{
console.log(val);
});
/*
[ 'job1', '自有可枚举属性1' ]
[ 'job2', '自有可枚举属性2' ]
*/
hasOwnProperty
检测一个对象自身属性中是否含有指定的属性,返回boolean
引用自MDN: JavaScript 并没有保护 hasOwnProperty 属性名,因此某个对象是有可能存在使用这个属性名的属性,所以直接使用原型链上的 hasOwnProperty 方法
代码清单81
2
3
4
5
6
7
8
9
10
11
12for(var attr in obj){
if(Object.prototype.hasOwnProperty.call(obj,attr)){
console.log("自有属性::",attr);
}else{
console.log("继承属性::",attr);
}
}
/*
自有属性:: job1
自有属性:: job2
继承属性:: name
*/
propertyIsEnumerable
检测一个属性在指定的对象中是否可枚举,返回boolean
代码清单91
2
3
4
5
6
7
8
9
10
11
12
13
14Reflect.ownKeys(obj).map((attr) => {
if (Object.prototype.propertyIsEnumerable.call(obj, attr)) {
console.log("可枚举属性::", attr);
} else {
console.log("不可枚举属性::", attr);
}
});
/*
可枚举属性:: job1
可枚举属性:: job2
不可枚举属性:: address
可枚举属性:: Symbol(自有可枚举symbol)
不可枚举属性:: Symbol(自有不可枚举symbol)
*/