【亡羊补牢】JS灵魂之问 第27期 自己实现一个 Proxy

引言

本篇要讲解的内容是关于 自己实现一个 Proxy ,那今天这篇看能不能问倒你了,一起来探索一下吧。

仰望星空的人,不应该被嘲笑

自己实现一个 Proxy

其实,有了前置知识,我们不难发现,ProxyObject.defineProperty 实现效果是一样的,但其实两个原理上是有挺大差别的。

  • defineProperty 操作的是空对象,而 proxy 操作的是现有对象。
  • defineProperty 原本目的是对一个对象赋予对应属性,而 proxy代理是操作原本就有属性的对象。其主要功能是自定义对象属性的获取、赋值、枚举、函数调用等

那么,我们首先看看 Proxy是怎样使用的,看一下下面这个例子,然后我们再用 defineProperty 自己实现一个 Proxy

let target = {
    
    
  a: 1,
  b: 2
}

let proxy = new Proxy(target, {
    
    
  get(target, prop) {
    
    
    return 'Get:' + prop + '=' + target[prop];
  },
  set(target, prop, newVal) {
    
    
    target[prop] = newVal;
    console.log('Set:' + prop + '=' + newVal);
  }
})

console.log(proxy.a);
proxy.b = 3;

打印结果如下:

Get:a=1
Set:b=3
let target = {
    
    
  a: 1,
  b: 2
}
function MyProxy(target, handler) {
    
    
  // 操作副本
  let _target = deepClone(target);
  Object.keys(_target).forEach((key) => {
    
    
    Object.defineProperty(_target, key, {
    
    
      get() {
    
    
        return handler.get && handler.get(target, key);
      },
      set(newVal) {
    
    
        return handler.set && handler.set(target, key, newVal);
      }
    })
  })
  return _target;
}
// 实现深拷贝
function deepClone(org, tar) {
    
    
  var tar = tar || {
    
    },
    toStr = Object.prototype.toString,
    arrType = 'Array';
  for (var key in org) {
    
    
    if (org.hasOwnProperty(key)) {
    
    
      if (typeof org[key] === 'object' && typeof org[key] !== 'null') {
    
    
        tar[key] = toStr.call(org[key]).slice(8, -1) === arrType ? [] : {
    
    };
        deepClone(org[key], tar[key]);
      } else {
    
    
        tar[key] = org[key];
      }
    }
  }
  return tar;
}

let proxy = new MyProxy(target, {
    
    
  get(target, prop) {
    
    
    return 'Get:' + prop + '=' + target[prop];
  },
  set(target, prop, newVal) {
    
    
    target[prop] = newVal;
    console.log('Set:' + prop + '=' + newVal);
  }
})
console.log(proxy.a);
proxy.b = 3;

打印结果如下,和上述源代码结果一样。

Get:a=1
Set:b=3

这里再进行梳理一下,MyProxy 实现原理是首先,先拷贝一份原对象,因为原本的 Proxy就是返回了一个代理对象,而我们先深拷贝一份对象,然后遍历这个拷贝对象,依次让对象的属性通过 Object.defineProperty 来实现数据劫持的效果,里面用到了 getset 方法,而getset时直接操作我们的原对象就是,这样当我们对代理对象(即我们一开始拷贝的对象)操作时,就会劫持我们的 getset方法,这样就能直接操作原对象了。

最终效果就是我们自定义了对象属性的获取、赋值的方式,不直接操作原对象,而是操作这个代理对象即可。

最后

文章产出不易,还望各位小伙伴们支持一波!

往期精选:

小狮子前端の笔记仓库

访问超逸の博客,方便小伙伴阅读玩耍~

学如逆水行舟,不进则退

猜你喜欢

转载自blog.csdn.net/weixin_42429718/article/details/108723195