JS中可枚举属性(enumerable)和propertyIsEnumerable()

什么是可枚举属性

枚举就是列举,可枚举属性就是可以列举的属性,直白一点就是可以用for in遍历到的属性。

propertyIsEnumerable()的用法

obj.propertyIsEnumerable(prop) 是用来判断属性是否可枚举的

  • obj: 要检测的对象
  • 参数 prop: 要检测的属性的名称。
  • 返回值: Boolean类型,可枚举属性的时候返回true。

可枚举属性会对那些操作产生影响

for…in
Object.keys()
JSON.stringify()

下面我们详细测试一下

1. 可枚举属性的遍历

首先我们看一个栗子:

var p = {name: '张三', age: 28};
for (var key in p) {
    console.log('属性名:' + key + ',是否可枚举:' + p.propertyIsEnumerable(key));
}
//输出结果:
//->属性名:name,是否可枚举:true
//->属性名:age,是否可枚举:true

p上的name和age两个属性都被遍历了,这两个属性都是可枚举属性,那什么是不可枚举属性呢?

2. 不可枚举属性不会被遍历

我们再看一个栗子:

Object.prototype.get_name = function () {
    return this.name;
};
var p = new Object({name: '张三'});
for (var key in p) {
    console.log('属性名:' + key + ',是否可枚举:' + p.propertyIsEnumerable(key));
}
//输出结果:
// ->属性名:name,是否可枚举:true
// ->属性名:get_name,是否可枚举:false

可能有疑问get_name判断可枚举返回的是false怎么还遍历出来了呢?其实正确的理解是这样的, get_name不是实例p的属性是Object原型上的属性,对于实例p来说是不可枚举的,但是对于原型来说是可枚举的(下面代码有测试)。(for…in遍历,只要在遍历对象和对象所在的原型链上的可枚举属性都会被遍历)
大家想一个问题,get_name是Object的原型上的属性,被遍历了。Object的原型上还有很多的属性,有toString、hasOwnProperty还有我们现在正在研究的propertyIsEnumerable都是原型上的属性,怎么就只有自定义的get_name被遍历出来了呢?因为其它属性都是不可枚举的。看下面代码:

console.log(p.__proto__.propertyIsEnumerable('get_name'));//->true
console.log(p.__proto__.propertyIsEnumerable('toString'));//->false
console.log(p.__proto__.propertyIsEnumerable('propertyIsEnumerable'));//->false
console.log(p.__proto__.propertyIsEnumerable('hasOwnProperty'));//->false

我们已经知道了什么是可枚举属性,知道了propertyIsEnumerable得用法,我们可不可以自定义一个不可枚举属性呢?当然可以。

3. 自定义不可枚举属性

var p = new Object({name: '张三'});
//为p设置不可枚举属性
Object.defineProperty(p, "age", {
    value: 20,
    enumerable: false
});
for (var key in p) {
    console.log('属性名:' + key + ',是否可枚举:' + p.propertyIsEnumerable(key));
}
//输出结果:属性名:name,是否可枚举:true
console.log('age是不是p的可枚举属性:' + p.propertyIsEnumerable('age')+',age属性的值是多少:'+ p.age);
//age是不是p的可枚举属性:false,age属性的值是多少:20

通过defineProperty我们就自定义了一个不可枚举的属性,并且可以正常使用。

4. 不可枚举属性对Object.keys()和JSON.stringify()的影响

Object.keys()和JSON.stringify()也不会列举出不可枚举属性,也不会列举出原型链上的所有属性。

Object.prototype.get_name = function () {};
var p = new Object({name: '张三'});
//为p设置不可枚举属性
Object.defineProperty(p, "age", {
    value: 20,
    enumerable: false
});
console.log(Object.keys(p));//输出结果->["name"]
console.log(JSON.stringify(p));//输出结果->{"name":"张三"}

如果文档哪里不正确欢迎指正。
本文主要参考文档:http://www.cnblogs.com/kongxy/p/4618173.html
欢迎转载,但请注明出处。

点赞