Object.defineProperty() 学习

Object.defineProperty() 学习
最新回答
惹我细心溺屎身亡

2022-08-14 14:36:40

Object.defineProperty() 是 JavaScript 中用于直接在对象上定义新属性或修改现有属性的方法,它是实现数据响应式(如 Vue 2.0)的核心机制。以下是关键知识点总结:

1. 基本语法Object.defineProperty(obj, prop, descriptor)
  • obj: 目标对象。
  • prop: 要定义或修改的属性名(字符串或 Symbol)。
  • descriptor: 属性描述符,分为数据描述符存取描述符
2. 属性描述符详解数据描述符(可选 value 或 writable)
  • value: 属性值(默认 undefined)。
  • writable: 是否可修改值(true/false)。
  • enumerable: 是否可枚举(如 for...in 或 Object.keys())。
  • configurable: 是否可删除或修改描述符(除 value 和 writable)。
存取描述符(可选 get 或 set)
  • get: 获取属性值的函数。
  • set: 设置属性值的函数。

注意:数据描述符和存取描述符不能混用,否则会报错。

3. 关键特性与示例不可写属性const obj = {};Object.defineProperty(obj, 'name', { value: 'Ken', writable: false });obj.name = 'New'; // 非严格模式静默失败,严格模式报错console.log(obj.name); // 'Ken'不可枚举属性const obj = {};Object.defineProperty(obj, 'secret', { value: '123', enumerable: false });console.log(Object.keys(obj)); // []不可配置属性const obj = {};Object.defineProperty(obj, 'id', { value: 1, configurable: false });delete obj.id; // 静默失败Object.defineProperty(obj, 'id', { enumerable: true }); // 报错自定义 Getter/Setterconst obj = { _name: 'Ken' };Object.defineProperty(obj, 'name', { get() { return this._name; }, set(newVal) { this._name = `Name: ${newVal}`; }});obj.name = 'NaNa';console.log(obj.name); // 'Name: NaNa'4. 高级用法继承属性控制

通过 Object.create(null) 创建无原型链的对象,避免继承属性干扰:

const obj = Object.create(null);Object.defineProperty(obj, 'key', { value: 'static' });冻结原型链

防止修改 Object.prototype 的默认属性:

(Object.freeze || Object)(Object.prototype);Symbol 属性

Symbol 属性也可被定义为可枚举:

const obj = {};Object.defineProperty(obj, Symbol('id'), { value: 1, enumerable: true });5. Vue 2.0 响应式原理

Vue 通过 Object.defineProperty() 拦截数据属性的 get 和 set,实现依赖收集和派发更新:

function defineReactive(obj, key, val) { const dep = new Dep(); // 依赖收集器 Object.defineProperty(obj, key, { get() { dep.depend(); // 收集依赖 return val; }, set(newVal) { if (newVal === val) return; val = newVal; dep.notify(); // 通知更新 } });}6. 注意事项
  1. 性能开销:大量使用 Object.defineProperty() 可能影响性能(Vue 3 改用 Proxy)。
  2. 数组监听:需重写数组方法(如 push、pop)实现响应式。
  3. 默认值:未指定的描述符默认为 false 或 undefined。
总结

Object.defineProperty() 提供了精细控制对象属性的能力,是理解 JavaScript 对象行为和框架响应式原理的基础。通过合理配置描述符,可以实现数据保护、动态计算属性等高级功能。