返回专题

专题 2018

DefineProperty

DefineProperty 相关笔记

JavaScript面试题
本文目录2
  1. DefineProperty
  2. Proxy

DefineProperty

JavaScript
const handler = {
  get: () => {
    console.log('get');
    return obj['test'];
  },
  set: value => {
    console.log('set', { value });
    obj['test'] = value;
  },
};

const obj = {
  test: {},
  test2: {},
};
const proxy = Object.defineProperties(
  { ...obj },
  {
    test: handler,
  }
);

console.log('# proxy.test.a -> get');
proxy.test.a;

console.log('# proxy.test.a = 1 -> get');
proxy.test.a = 1;

console.log("# proxy.test['a'] = 1 -> get");
proxy.test['a'] = 1;

console.log('# proxy.test -> get');
proxy.test;

console.log('# proxy.test = {} -> set');
proxy.test = {};

console.log("# proxy['test'] = {} -> set");
proxy['test'] = {};

// 结论: 添加监听的时候只能一个一个添加监听, 不能监听未定义的对象
// 不能监听 delete
// 直接对 proxy.test 进行赋值, 获取会正常触发
// 对 proxy.test[PROPERTY] 进行赋值, 获取只会触发 get 监听
// 对 test[PROPERTY] 进行操作则不会触发监听

Proxy

JavaScript
const handler = {
  get: (target, key, receiver) => {
    const result = Reflect.get(target, key, receiver);
    console.log('get', { target, key });
    return result;
  },
  set: (target, key, value, receiver) => {
    const result = Reflect.set(target, key, value, receiver);
    console.log('set', { target, key, value });
    return result;
  },
  deleteProperty: (target, key) => {
    const result = Reflect.deleteProperty(target, key);
    console.log('deleteProperty', { target, key });
    return result;
  },
};

const proxy = new Proxy(
  {
    test: {
      a: 12,
    },
  },
  handler
);

proxy.test = 123;
proxy.test

// 结论:
// proxy 只会对对象的属性的第一层添加监听
// 直接对 proxy.test 进行赋值, 删除, 获取会正常触发
// 对 proxy.test[PROPERTY] 进行赋值, 删除, 获取只会触发 get 监听
// 对 test[PROPERTY] 进行操作则不会触发监听
// 千万不要在get方法中读取receiver的属性,因为receiver实质上就是proxy自身,所以receiver.key这句代码就等同于proxy.key,会重新调用get方法导致死循环
返回首页
上一篇函数的合成与科里化下一篇Express vs Koa

Discussion

留言与讨论

想法、补充和不同意见都欢迎。