什么是可枚举属性,什么是不可枚举属性?

315 阅读3分钟

在 JavaScript 中,每个对象都有属性。这些属性可以被分类为可枚举属性和不可枚举属性。这个分类是基于属性描述符的一个属性特性。

可枚举属性是指可以被枚举(遍历)的属性,也就是可以在循环或使用内置方法(如 Object.keys())中获取到的属性。默认情况下,大多数对象的自有属性都是可枚举的。

不可枚举属性是指不能被枚举的属性,也就是无法通过循环或使用内置方法获取到的属性。不可枚举属性通常是一些内部使用的属性或特殊属性。

要了解一个属性是可枚举还是不可枚举,可以使用 Object.getOwnPropertyDescriptor() 方法来获取属性的描述符,然后查看 enumerable 属性。属性描述符包含了属性的各种特性,包括可枚举性。

下面是一个示例,演示如何判断属性的可枚举性:

javascript
const obj = {
  foo: 'bar',
  baz: 42
};

const propertyDescriptor1 = Object.getOwnPropertyDescriptor(obj, 'foo');
console.log(propertyDescriptor1.enumerable); // true

const propertyDescriptor2 = Object.getOwnPropertyDescriptor(obj, 'baz');
console.log(propertyDescriptor2.enumerable); // true

// 创建一个不可枚举属性
Object.defineProperty(obj, 'qux', {
  value: 'quux',
  enumerable: false
});

const propertyDescriptor3 = Object.getOwnPropertyDescriptor(obj, 'qux');
console.log(propertyDescriptor3.enumerable); // false

// 遍历对象的属性
for (const key in obj) {
  console.log(key); // 输出:foo, baz
}

在上面的示例中,属性 foobaz 默认是可枚举的,所以在循环中可以获取到它们。而属性 qux 是通过使用 Object.defineProperty() 方法创建的不可枚举属性,所以它在循环中不会被获取到。

需要注意的是,某些内置对象的一些属性可能是不可枚举的,这是为了保护它们的完整性和不被意外修改。但大多数自定义对象的属性默认都是可枚举的。如果需要创建不可枚举属性,可以使用 Object.defineProperty() 方法显式设置 enumerable 属性为 false

**

t

详细一点

好的,让我们更详细地探讨可枚举属性和不可枚举属性的概念。

可枚举属性(Enumerable Properties):

  1. 默认可枚举: 大多数对象属性默认都是可枚举的,这意味着它们可以被 for...in 循环、Object.keys()Object.values() 等方法枚举出来。

  2. 迭代方法: 当你使用 for...in 循环遍历对象时,只会迭代可枚举属性。例如:

    javascript
    const obj = { a: 1, b: 2, c: 3 };
    
    for (const key in obj) {
      console.log(key); // 输出:a, b, c
    }
    
  3. Object.keys() 和 Object.values(): 这两个方法也只返回可枚举属性的键或值。

    javascript
    const obj = { a: 1, b: 2, c: 3 };
    
    console.log(Object.keys(obj)); // 输出:['a', 'b', 'c']
    console.log(Object.values(obj)); // 输出:[1, 2, 3]
    
  4. 默认情况下创建属性是可枚举的: 当通过简单的赋值创建属性时,默认情况下该属性是可枚举的。

    javascript
    const obj = {};
    obj.foo = 'bar';
    
    console.log(Object.getOwnPropertyDescriptor(obj, 'foo').enumerable); // 输出:true
    

不可枚举属性(Non-enumerable Properties):

  1. 默认不可枚举: 有一些属性默认是不可枚举的,例如一些内建对象的原型链上的属性。

    javascript
    console.log(Object.getOwnPropertyDescriptor([], 'length').enumerable); // 输出:false
    
  2. Object.defineProperty(): 可以使用 Object.defineProperty() 方法创建不可枚举属性。

    javascript
    const obj = {};
    
    Object.defineProperty(obj, 'nonEnumerable', {
      value: 'This is not enumerable',
      enumerable: false
    });
    
    console.log(Object.keys(obj)); // 输出:[]
    
  3. for...in 不迭代不可枚举属性: 使用 for...in 循环时,不会迭代不可枚举属性。

    javascript
    const obj = {};
    Object.defineProperty(obj, 'nonEnumerable', {
      value: 'This is not enumerable',
      enumerable: false
    });
    
    for (const key in obj) {
      console.log(key); // 输出:无输出,因为属性不可枚举
    }
    
  4. Object.getOwnPropertyNames(): 可以使用 Object.getOwnPropertyNames() 方法获取对象的所有属性,包括不可枚举属性。

    javascript
    console.log(Object.getOwnPropertyNames(obj)); // 输出:['nonEnumerable']
    

总体而言,可枚举属性适用于那些你希望在迭代或序列化时考虑的属性,而不可枚举属性更适用于一些内部实现细节或不希望被外部代码轻易访问的属性。