Object.defineProperty()

59 阅读2分钟

一、基本语法

Object.defineProperty(obj, prop, descriptor)
  • obj:目标对象
  • prop:要定义或修改的属性名
  • descriptor:属性描述符(包含配置信息)

二、属性描述符类型

分为 数据描述符存取描述符,二者不可混用。

1. 数据描述符

  • value:属性值(默认undefined
  • writable:是否可修改(默认false
  • enumerable:是否可枚举(如出现在for...in循环中,默认false
  • configurable:是否可删除或重新配置(默认false

示例

const obj = {};
Object.defineProperty(obj, 'a', {
  value: 42,
  writable: false,
  enumerable: true,
  configurable: true
});
obj.a = 100; // 静默失败(严格模式报错)
console.log(obj.a); // 42

2. 存取描述符

  • get:获取属性值的函数(默认undefined
  • set:设置属性值的函数(默认undefined

示例

let internalValue = 0;
Object.defineProperty(obj, 'b', {
  get() {
    return internalValue;
  },
  set(newVal) {
    internalValue = newVal;
    console.log('值被修改为:', newVal);
  },
  enumerable: true
});
obj.b = 5; // 输出 "值被修改为:5",会调用set方法。另外要使用中间变量,不能使用obj.属性名这种
,会一直递归直至栈溢出```

### 三、关键特性说明
1. **默认值**:除`value`默认为`undefined`外,`writable`、`enumerable`、`configurable`默认均为`false`。
2. **configurable: false** 时:
   - 不能修改除`writable`之外的描述符(`writable`只能从`true`改为`false`)
   - 不能删除属性
3. **应用场景**:
   - 实现数据响应式(如Vue2的响应式核心)
   - 控制属性的访问和修改权限
   - 隐藏内部实现细节(通过不可枚举性)

### 四、与直接赋值的区别
```javascript
obj.c = 10; // 等价于:
Object.defineProperty(obj, 'c', {
  value: 10,
  writable: true,
  enumerable: true,
  configurable: true
});

五、注意事项

  • 性能:频繁调用会影响性能,尤其在大型对象上
  • 兼容性:ES5+支持,IE9+基本支持
  • 局限性:无法监听新增属性(需配合Object.defineProperties()或使用Proxy)

六、简单响应式示例

const data = {};
let domElement = document.getElementById('display');

let _value;
Object.defineProperty(data, 'message', {
  get() {
    return _value;
  },
  set(newVal) {
    _value = newVal;
    domElement.textContent = newVal; // 自动更新DOM
  }
});

data.message = 'Hello World!'; // 页面显示更新