可枚举与不可枚举

先把总结写在这里:

  1. JavaScript对象的属性可分为可枚举和不可枚举,它是由属性的enumeration值决定的,true为可枚举,false为不可枚举
  2. js中原型属性一般是不可枚举的,而自己定义的属性一般是可枚举的
  3. 可以通过propertylsEnumerable()方法判断该属性是否可枚举
  4. 属性的枚举性会影响以下三个函数的结果
    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() 语法

  1. 语法:obj.propertyIsEnumerable(prop)
  2. 描述:每个对象都有一个propertyIsEnumerable方法。此方法可以确定对象中指定的属性是否可枚举,返回一个布尔值。但该方法对通过原型链继承的属性无效(原型链继承的属性是否可枚举不能用该方法来判断)
  3. 案例:
    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,所以该方法对其无效。

猜你喜欢

转载自blog.csdn.net/weixin_40374953/article/details/85319512
今日推荐