最近在项目里使用了 Proxy,遇到一些问题记录一下javascript
简单来讲 Proxy 是对对象
设置一个拦截,直接上代码java
let obj = {
attr: 1
};
// 对 obj 进行拦截
obj = new Proxy(obj, {
get: function (target, key, receiver) {
//若是 obj 有这个属性,则直接返回
if(key in target) {
return target[key];
}
//若是 obj 没有这个属性,则统一返回 '没有这个值'
return '没有这个值';
},
set: function (target, key, value, receiver) {
// 想设置对象属性,直接返回(不让设置)
return true;
}
});
// 使用
console.log(obj.attr); // 输出 1
console.log(obj.abc); // 输出 '没有这个值',
obj.attr = 2;//
console.log(obj.attr); // 输出 1, 不能设置对象属性
复制代码
能够进行的拦截类型不止 get, set
,还有不少,例如:(来自阮一峰老师的书 ES6 Proxy):es6
如上这些都是介绍都是直接拷贝的 阮一峰老师的书 ES6 Proxychrome
一、拦截时的 this
指向问题 阮老师书里也有说起数组
在拦截方法里,this
指向 Proxy 对象,因此在调用原对象的方法时,须要注意,直接看代码浏览器
let div = document.querySelector('div'); // 随便拿一个页面的 div, 对他进行代理
// 第一种代理方法
let divProxy = new Proxy(div, {
get: function (target, key, receiver) {
// 访问这个 div 的任何属性,都直接返回
return target[key];
}
});
// 调用 div 的 querySelector 方法,拿他下边的 a 标签
console.log(divProxy.querySelector('a')); // chrome 上会报错:Uncaught TypeError: Illegal invocation
复制代码
如上的代码,猜想由于 querySelector 方法内部有访问 this
指向,致使报错。修改成以下代码,则能够修复这个问题:babel
let div = document.querySelector('div'); // 随便拿一个页面的 div, 对他进行代理
// 第二种代理方法
let divProxy = new Proxy(div, {
get: function (target, key, receiver) {
if( !!target[key] && !!target[key].bind) {
// 使用 bind 绑定 this 指向
return target[key].bind(target);
} else {
return target[key];
}
}
});
console.log(divProxy.querySelector('a')); // <a href='https://t.tt'>来买呀</a>
复制代码
另外还有一个问题,经过代理设置对象属性时,也会有问题相同的,看代码吧app
let div = document.querySelector('div');
let divProxy = new Proxy(div, {});
// 设置 div 的 innerHTML 属性,设置对象属性默认实际上是调用 `div.innerHTML.__defineSetter__` 方法
divProxy.innerHTML = '<a href="https://t.tt">来买呀</a>'; //chrome 报错: Uncaught TypeError: Illegal invocation
复制代码
直接上解决办法函数
let div = document.querySelector('div');
let divProxy = new Proxy(div, {
// 拦截全部的 set 行为
set: function (target, key, value, receiver) {
if(key in target) {
target[key] = value; // 直接调用原对象属性进行设置(target[key])
}
return true;
}
});
divProxy.innerHTML = '<a href="https://t.tt">来买呀</a>';
复制代码
通常 Proxy
会和 Reflect
一块儿使用,本文不作介绍了,直接上阮老师的书;ui
JavaScript 的语法愈来愈规范,以前的一些坑,新的标准规范也开始慢慢填,加上babel
的普及使用,咱们能够多多拥抱新语法、特性,简洁代码,愉悦本身。