我们一般认为,可以被for in遍历出来的属性就是可枚举属性,否则就是不可枚举属性。对象的属性的可枚举性和不可枚举性是由属性的enumerable值决定的,true为可枚举,false为不可枚举。
js中基本包装类型的原型属性是不可枚举的,如Object, Array, Number,Function,Date等,而自己定义的属性一般可枚举,举例:
var fun = new Function()
for (var key in fun) {
console.log(key); // 什么也没打印出来
}
var num = new Number()
for(var key in num) {
console.log(key) // 什么也没打印出来
}
var info = {
name: '张三',
age: 18
}
for(var key in info) {
console.log(key) // name,age
}
属性的可枚举或者不可枚举影响以下几个操作的结果for...in、Object.keys()、JSON.stringify()和Object.assign() 。举例:
function Person() {
this.name = '张三'
}
Person.prototype.age = 18
var p = new Person()
Object.defineProperty(p, 'sex', {
value: '男',
enumerable: false
})
// for in
for (var key in p) {
console.log(key) // name,age
}
// Object.keys()
Object.keys(p).map(key => {
console.log(key) // name
})
// JSON.stringify()
console.log(JSON.stringify(p)) // {"name":"张三"}
// Object.assign()
console.log(Object.assign({},p)) // {name: "张三"}
由上可以看出:
1、for in 遍历对象的每一个可枚举属性,包括原型链上的可枚举属性
2、Object.keys() 只能遍历自己对象上的可枚举属性,不能遍历自己原型上的可枚举属性
3、JSON.stringify() 只能读取对象本身的可枚举属性,并序列化为JSON对象
4、Object.assign() 会忽略enumerable为false的属性,只合并对象自身的可枚举的属性
Object.getOwnPropertyNames()可以读取对象本身的所有属性,不管enumerable的值
function Person() {
this.name = '张三'
}
Person.prototype.age = 18
var p = new Person()
Object.defineProperty(p, 'sex', {
value: '男',
enumerable: false
})
Object.getOwnPropertyNames(p).forEach(key=>{
console.log(key) // name,sex
})
可以通过propertyIsEnumerable方法判断该属性是否可枚举
function Person() {
this.name = '张三'
}
Person.prototype.age = 18
var p = new Person()
Object.defineProperty(p, 'sex', {
value: '男',
enumerable: false
})
console.log(p.propertyIsEnumerable('name')) // true
console.log(p.propertyIsEnumerable('age')) // false
console.log(p.propertyIsEnumerable('sex')) // false