先把总结写在这里:
- JavaScript对象的属性可分为可枚举和不可枚举,它是由属性的enumeration值决定的,true为可枚举,false为不可枚举
- js中原型属性一般是不可枚举的,而自己定义的属性一般是可枚举的
- 可以通过propertylsEnumerable()方法判断该属性是否可枚举
- 属性的枚举性会影响以下三个函数的结果
1)for...in //遍历原型与实例上的所有可枚举属性
2)Object.keys(); //只能返回对象本身具有的可枚举属性。
3)JSON.stringify(); //只能读取对象本身的可枚举属性,并序列化为JSON对象。4)Object.getOwnPropertyNames() //遍历自身所有属性(不论是否是可枚举的),不包括原型链上面的.。
上面说了JavaScript对象的属性是否可枚举是又enumeration的值决定的,那么enumeration是什么,它的值又是什么时候去设置的呢?
enumeration是 Object.defineProperty()方法的一个参数,下面来看看怎么去设置 一个属性是否可枚举。
var person = {
name:'zhou',
age: '12',
sex: 'girl'
}
Object.defineProperty(person,'age',{
enumerable:true,//可以被枚举
});
Object.defineProperty(person,'sex',{
enumerable:false,//可以被枚举
})
for(var k in person){
console.log(person[k])//a,可以被枚举
}
//12
//zhou
如何设置是否可枚举-- enumerable
由上面的点可以看出:
1.Object.defineProperty(obj, prop, descriptor)方法有三个参数,每个参数各代表着
第一个:目标属性所在的对象,
第二个:目标属性,放在字符串里,
第三个:目标属性的行为,放在对象里;
2.enumerable为true表示可枚举,enumerable为false表示不可枚举;
3.开发者自定义的对象person的所有属性都是可枚举的;
如何判断是否可枚举-- propertyIsEnumerable
在不知情的情况下,我们如何判断一个属性是否可枚举呢?propertylsEnumerable()方法可以解决这个问题,对于上面的例子来看看他是怎么用的
person.propertyIsEnumerable('sex');//false
person.propertyIsEnumerable('age');//true
propertyIsEnumerable() 语法
- 语法:obj.propertyIsEnumerable(prop)
- 描述:每个对象都有一个propertyIsEnumerable方法。此方法可以确定对象中指定的属性是否可枚举,返回一个布尔值。但该方法对通过原型链继承的属性无效(原型链继承的属性是否可枚举不能用该方法来判断)
- 案例:
1)用户自定义对象和引擎内置对象的区别
var o = {};
var a = [];
o.prop = 'is enumerable';
a[0] = 'is enumerable';
o.propertyIsEnumerable('prop'); // 返回 true
a.propertyIsEnumerable(0); // 返回 true
Math.propertyIsEnumerable('random'); // 返回 false
Object.propertyIsEnumerable('constructor'); // 返回 false
对于基本包装类型的原型属性是不可枚举的,如Object, Array, Number等
var num = new Number();
for(var pro in num) {
console.log("num." + pro + " = " + num[pro]);
}
它的输出结果会是空。这是因为Number中内置的属性是不可枚举的,所以不能被for…in访问到。
说明开发者自定义的属性在一般情况下是可枚举的,而内置特殊对象Math和基本包装类型的原型属性是不可枚举的,如Object, Array, Number等
2)自身属性和继承属性
//构造函数
function firstConstructor() {
this.property = 'is not enumerable';
}
firstConstructor.prototype.firstMethod = function() {};
//继承
function secondConstructor() {
this.method = function method() { return 'is enumerable'; };
}
secondConstructor.prototype = new firstConstructor;
secondConstructor.prototype.constructor = secondConstructor;
//实例
var o = new secondConstructor();
o.arbitraryProperty = 'is enumerable';
//打印出实例
console.dir(o)
我们来看看打印出来的实例对象,看看那些那些属性是自身的,那些属性是在原型上的
再看看for/in遍历出来的枚举属性的
最后来看看这些属性在propertyIsEnumerable()上返回的值
console.log(o.propertyIsEnumerable('arbitraryProperty')); // 返回 true
console.log(o.propertyIsEnumerable('method')); // 返回 true
console.log(o.propertyIsEnumerable('prototype')); // 返回 false
console.log(o.propertyIsEnumerable('constructor')); // 返回 false
console.log(o.propertyIsEnumerable('firstMethod')); // 返回 false
说明propertyIsEnumerable方法只对对象自身的属性(对象自身添加的、构造函数实例化的)有效,对原型上的、继承来的属性都无效。
例如图二的属性丢失可枚举的,但是在原型上的属性propertyIsEnumerable()方法却都返回false,所以该方法对其无效。