# 属性描述符 - DeepSeek

在 JavaScript 中，属性描述符（Property Descriptor）是用于描述对象属性特性的对象。每个对象的属性都有一个对应的属性描述符，它定义了该属性的行为。属性描述符分为两种类型：**数据描述符**和**存取描述符**。

#### 1. 数据描述符（Data Descriptor）

数据描述符用于描述一个具有值的属性，包含以下可选键：

* **value**: 属性的值，默认为 `undefined`。
* **writable**: 布尔值，表示属性值是否可以被修改，默认为 `false`。
* **enumerable**: 布尔值，表示属性是否可以在 `for...in` 循环或 `Object.keys()` 中被枚举，默认为 `false`。
* **configurable**: 布尔值，表示属性是否可以被删除或修改其特性（如将 `writable` 从 `false` 改为 `true`），默认为 `false`。

**示例：**

```javascript
const obj = {};

Object.defineProperty(obj, 'name', {
  value: 'Alice',
  writable: false,       // 不可修改
  enumerable: true,       // 可枚举
  configurable: false    // 不可删除或修改特性
});

console.log(obj.name); // Alice
obj.name = 'Bob';      // 静默失败（严格模式下会报错）
console.log(obj.name); // Alice

for (let key in obj) {
  console.log(key);    // name
}
```

***

#### 2. 存取描述符（Accessor Descriptor）

存取描述符用于描述一个通过 getter 和 setter 访问的属性，包含以下可选键：

* **get**: 函数，当访问属性时调用，默认为 `undefined`。
* **set**: 函数，当设置属性时调用，默认为 `undefined`。
* **enumerable**: 布尔值，表示属性是否可枚举，默认为 `false`。
* **configurable**: 布尔值，表示属性是否可配置，默认为 `false`。

**示例：**

```javascript
const obj = {
  _age: 25
};

Object.defineProperty(obj, 'age', {
  get() {
    return this._age;
  },
  set(value) {
    if (value > 0) {
      this._age = value;
    }
  },
  enumerable: true,
  configurable: true
});

console.log(obj.age); // 25
obj.age = 30;
console.log(obj.age); // 30
obj.age = -10;        // 设置无效
console.log(obj.age); // 30
```

***

#### 3. 获取属性描述符

可以使用 `Object.getOwnPropertyDescriptor` 方法获取某个属性的描述符。

**示例：**

```javascript
const obj = { name: 'Alice' };
const descriptor = Object.getOwnPropertyDescriptor(obj, 'name');

console.log(descriptor);
// 输出：
// {
//   value: 'Alice',
//   writable: true,
//   enumerable: true,
//   configurable: true
// }
```

***

#### 4. 修改属性描述符

使用 `Object.defineProperty` 或 `Object.defineProperties` 可以修改或定义属性的描述符。

**示例：**

```javascript
const obj = { name: 'Alice' };

Object.defineProperty(obj, 'name', {
  writable: false
});

obj.name = 'Bob'; // 静默失败（严格模式下会报错）
console.log(obj.name); // Alice
```

***

#### 5. 默认行为

当通过普通方式（如字面量或赋值）创建属性时，属性描述符的默认值为：

* `value`: 属性的值。
* `writable`: `true`。
* `enumerable`: `true`。
* `configurable`: `true`。

**示例：**

```javascript
const obj = { name: 'Alice' };
console.log(Object.getOwnPropertyDescriptor(obj, 'name'));
// 输出：
// {
//   value: 'Alice',
//   writable: true,
//   enumerable: true,
//   configurable: true
// }
```

***

#### 6. 注意事项

* 如果同时使用数据描述符和存取描述符（如同时设置 `value` 和 `get`），会抛出错误。
* 修改不可配置的属性（`configurable: false`）会抛出错误。
* 在严格模式下，违反 `writable: false` 或 `configurable: false` 的规则会抛出错误。

***

通过属性描述符，JavaScript 提供了对对象属性行为的细粒度控制，这在实现高级功能（如数据绑定、属性校验等）时非常有用。
