DefineProperty / Proxy

我们可以对一个对象进行赋值和取值

但是如果我们在赋值或取值的时候 需要进行一些操作

此时 我们该如何监听到数据的改变呢 实现数据监听呢

defineProperty

Object.defineProperty(obj, prop, descriptor)

  • obj: 要在其上定义属性的对象。

  • prop: 要定义或修改的属性的名称。

  • descriptor: 将被定义或修改的属性的描述符。

    • value: 直接给这个属性赋值

    • writable: 是否可修改 默认 false

    • enumerable: 是否可枚举(遍历拿值) 默认 false

    • configurable: 是否可删除 默认 false

    • set

    • get

注意:value/writable 和 set/get 不能同时出现

可理解为既然可以手动修改 则 value 必定会有值 且是可读写的

直接使用对象字面量则默认 descriptor 都为 true 若只指定 value 则默认 descriptor 都为 false

var o = {};

o.a = 1;
// 等同于:
Object.defineProperty(o, 'a', {
  value: 1,
  writable: true,
  configurable: true,
  enumerable: true,
});

// 另一方面,
Object.defineProperty(o, 'a', { value: 1 });
// 等同于:
Object.defineProperty(o, 'a', {
  value: 1,
  writable: false,
  configurable: false,
  enumerable: false,
});
var obj = {};

Object.defineProperty(obj, 'name', {
  // value: 'chou',
  // writable: true,
  enumerable: true,
  configurable: true,
  set(newValue) {
    value = newValue;
    console.log('set方法执行了');
  },
  get() {
    console.log('get方法执行了');
    return value;
  },
});

obj.name = 'chou';

console.log(obj.name);

// output
// set方法执行了
// get方法执行了
// chou

如果我们需要一次定义多个属性 则可以使用Object.defineProperties(obj, props)

var obj = {};
Object.defineProperties(obj, {
  property1: {
    value: 'Hello',
    writable: true,
  },
  property2: {
    value: 'Chou',
    writable: false,
  },
  // etc. etc.
});

Vue2 就是使用了这个 Api 来实现了数据监听 从而实现了它的响应式体系

proxy

Vue3 开始 将用 proxy 代替 defineProperty 那么它对比 defineProperty 有什么优势呢

proxy 对比 defineProperty 它的优势在于 defineProperty 只能截取到 set 和 get

而 proxy 有 13 种 拦截器可供选择 具体的每种拦截器可参考

const handler = {
  set(obj, prop, value) {
    obj[prop] = value;
    console.log(`${prop}属性的set方法执行了`);
  },
  get(obj, prop) {
    console.log(`${prop}属性的get方法执行了`);
    return obj[prop];
  },
  has(obj, key) {
    console.log('has方法执行了');
    if (key in obj) {
      return true;
    } else {
      return false;
    }
  },
};

var obj = new Proxy({}, handler);

obj.name = 'chou';
obj.age = 18;

console.log(obj.name);
console.log('name' in obj);

// output
// name属性的set方法执行了
// age属性的set方法执行了
// name属性的get方法执行了
// chou
// has方法执行了
// true

Last updated

Was this helpful?