可枚举属性

定义:指那些内部 “可枚举” 标志设置为 true 的属性,对于通过直接的赋值和属性初始化的属性,该标识值默认为即为 true,对于通过 Object.defineProperty 等定义的属性,该标识值默认为 false。可枚举的属性可以通过 for…in 循环进行遍历(除非该属性名是一个 Symbol)。

获取可枚举属性:

  • for-in
  • Object.keys

两者的区别:

  • 结果:for-in是遍历,而Objec.keys是返回一个数组

  • 原理:for-in会走原型链,而Object.keys不会,就是for-in会遍历到继承的可枚举属性,后者则只获取自身的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var obj = {
    a: 1,
    b: 2
    }
    console.log(Object.getOwnPropertyDescriptors(obj))
    Object.prototype.test = 2
    for(var x in obj) {
    console.log(x) //a,b,test
    }
    Object.keys(obj) //["a", "b"]

判断方法:

  • getOwnPropertyDescriptor方法获取指定对象指定属性的描述对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    var obj = {
    a: 1,
    b: 2
    }
    console.log(Object.getOwnPropertyDescriptor(obj, 'a'))
    {
    configurable: true
    enumerable: true
    value: 1
    writable: true
    __proto__: Object
    }
  • getOwnPropertyDescriptors方法返回指定对象所有自身属性(非继承属性的)描述对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var obj = {
    a: 1,
    b: 2
    }
    console.log(Object.getOwnPropertyDescriptors(obj))
    {
    a: {value: 1, writable: true, enumerable: true, configurable: true}
    b: {value: 2, writable: true, enumerable: true, configurable: true}
    __proto__: Object
    }
  • propertyIsEnumerable,返回一个布尔值表示,指定的属性是否可枚举

    1
    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
    30
    31
    var obj = {
    a: 1
    }
    console.log(Object.getOwnPropertyDescriptor(obj, 'a'))
    {
    configurable: true
    enumerable: true
    value: 1
    writable: true
    __proto__: Object
    }

    var arr = [1]
    console.log(Object.getOwnPropertyDescriptor(arr, 0))
    {
    configurable: true
    enumerable: true
    value: 1
    writable: true
    __proto__: Object
    }
    console.log(Object.getOwnPropertyDescriptor(arr, 'length'))
    {
    configurable: false
    enumerable: false
    value: 1
    writable: true
    __proto__: Object
    }
    //发现enumerable为true,所以属性a是可枚举的
    //我们发现数组的length的描述对象的enumerable属性是false,所以他是不可枚举,在for-in遍历的时候,遍历不到,类似的还有对象原型的toSring方法

不能枚举的属性:

  • js基本数据类型自带的原型属性不可枚举
  • 通过Object.defineProperty()方法指定的enumerable为false的属性不可枚举

总的来说,操作中引入继承的属性会让问题复杂化,大多数时候,我们只关心对象自身的属性。所以,尽量不要用for...in循环,而用Object.keys()代替

参考内容