vue-java-tutorials/vue2-tutorials/import-script/3-Object.defineProperty.md

2.3 KiB
Raw Blame History

Object.defineProperty 方法

一、基本概念

Object.defineProperty() 是 JavaScript 中用于直接在一个对象上定义一个新属性,或者修改一个对象的现有属性的方法。它允许精确控制属性的行为特性。

属性描述符详解

1. 数据描述符(已注释部分)

{
    value: 18,        // 属性值
    enumerable: true, // 是否可枚举for...in或Object.keys()
    writable: true,   // 是否可修改
    configurable: true // 是否可删除或修改特性
}

2. 存取描述符(实际使用部分)

{
    get() {
        // 读取属性时调用
        return age;
    },
    set(value) {
        // 设置属性时调用
        age = value;
    }
}

特性说明

特性 类型 默认值 描述
configurable 布尔 false 是否可删除属性或修改特性
enumerable 布尔 false 是否出现在枚举属性中
value 任意 undefined 属性值
writable 布尔 false 是否可被赋值运算符改变
get 函数 undefined 读取属性时调用的函数
set 函数 undefined 设置属性时调用的函数

使用场景

  1. 实现数据响应式如Vue2的核心实现
  2. 创建私有属性通过getter/setter控制访问
  3. 属性访问拦截(在读取或设置时执行额外操作)
  4. 定义不可枚举属性(如内置对象的一些方法)

注意事项

  1. 数据描述符value, writable和存取描述符get, set不能同时使用
  2. 默认情况下通过defineProperty添加的属性不可枚举、不可写、不可配置
  3. 在严格模式下setter必须设置一个参数否则会抛出错误
  4. getter不应有副作用如修改其他属性值

实现简单响应式

function defineReactive(obj, key, val) {
    Object.defineProperty(obj, key, {
        get() {
            console.log(`读取 ${key}: ${val}`);
            return val;
        },
        set(newVal) {
            console.log(`设置 ${key}: ${newVal}`);
            val = newVal;
        }
    });
}

const data = {};
defineReactive(data, 'message', 'Hello');