# 可枚举、不可枚举的属性

在javascript中,对象的属性分为可枚举和不可枚举,他们是由propertyenumerable值决定的。可枚举性决定了这个属性可否被for...in循环遍历到。

# 改变属性可枚举性

Object.defineProperty() (opens new window) 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

其中有一个属性enumerable,当且仅当该属性的enumerable键值为true时,该属性才会出现在对象的枚举属性中。默认为false

var Person = function (name) {
    this.name = name;
};

// 创建原型属性
Person.prototype.age = 26;

// 创建实例
var person = new Person('xiaog');

// 在person实例中创建不可枚举属性"job"
Object.defineProperty(person, 'job', {
    value: 'WEB',
    enumerable: false,
    configurable: true,
    writable: true,
});

# 遍历属性

# Object.keys()

只能返回自身可枚举属性

Object.keys(person); // ["name"]

# for in

自身/原型可枚举属性:返回自身可枚举属性和原型上的属性

for (var i in person) {
    console.log(i) // name age
}

# hasOwnProperty()

通过hasOwnProperty,我们过滤了那些从原型链上继承的可枚举属性,只保留了name这个自身可枚举属性。

和in运算符不同,该方法会忽略掉那些从原型链上继承到的属性。

for (i in person) {
    if (Object.hasOwnProperty(i)) {
        console.log(i); // "name"
    }
}

# JSON.stringify()

此方法也只能读取对象本身的可枚举属性,并序列化为JSON对象。

JSON.stringify(isaac)   // "{"name":"xiaog"}"

# getOwnPropertyNames()

返回可枚举与不可枚举的自身属性。

Object.getOwnPropertyNames(person) // ["name", "job"]

# 自身+原型 所有属性

那么如何获取自身属性和原型属性,包括可枚举和不可枚举的属性呢

// 获取所有属性方法封装
function getAllPropertyNames( obj ) {
  var props = [];

  do {
    Object.getOwnPropertyNames( obj ).forEach(function ( prop ) {
      if ( props.indexOf( prop ) === -1 ) {
          props.push( prop );
      }
    });
  } while ( obj = Object.getPrototypeOf( obj ) );

  return props;
}

function getAllPropertyNames( obj ) {
  var props = [];

  do {
      props= props.concat(Object.getOwnPropertyNames( obj ));
  } while ( obj = Object.getPrototypeOf( obj ) );

  return props;
}