引言
本篇要讲解的内容是关于 自己实现一个 Proxy
,那今天这篇看能不能问倒你了,一起来探索一下吧。
仰望星空的人,不应该被嘲笑
文章目录
自己实现一个 Proxy
其实,有了前置知识,我们不难发现,Proxy
和 Object.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
来实现数据劫持的效果,里面用到了 get
和 set
方法,而get
和 set
时直接操作我们的原对象就是,这样当我们对代理对象(即我们一开始拷贝的对象)操作时,就会劫持我们的 get
和 set
方法,这样就能直接操作原对象了。
最终效果就是我们自定义了对象属性的获取、赋值的方式,不直接操作原对象,而是操作这个代理对象即可。
最后
文章产出不易,还望各位小伙伴们支持一波!
往期精选:
访问超逸の博客,方便小伙伴阅读玩耍~
学如逆水行舟,不进则退