JavaScript Proxy基本知识梳理( 三 )


JavaScript Proxy基本知识梳理

文章插图
 
上面代码中 , obj.foo属性不可写 , Proxy 对这个属性的set代理将不会生效 。
注意 , 严格模式下 , set代理如果没有返回true , 就会报错 。
JavaScript Proxy基本知识梳理

文章插图
 
上面代码中 , 严格模式下 , set代理返回false或者undefined , 都会报错 。
Apply()
apply方法拦截函数的调用、call和apply操作 。
apply方法可以接受三个参数 , 分别是目标对象、目标对象的上下文对象(this)和目标对象的参数数组 。
JavaScript Proxy基本知识梳理

文章插图
 
下面是一个例子 。
JavaScript Proxy基本知识梳理

文章插图
 
上面代码中 , 变量p是 Proxy 的实例 , 当它作为函数调用时(p()) , 就会被apply方法拦截 , 返回一个字符串 。
下面是另外一个例子 。
JavaScript Proxy基本知识梳理

文章插图
 
上面代码中 , 每当执行proxy函数(直接调用或call和apply调用) , 就会被apply方法拦截 。
另外 , 直接调用Reflect.apply方法 , 也会被拦截 。
JavaScript Proxy基本知识梳理

文章插图
 
has()
has方法用来拦截HasProperty操作 , 即判断对象是否具有某个属性时 , 这个方法会生效 。典型的操作就是in运算符 。
has方法可以接受两个参数 , 分别是目标对象、需查询的属性名 。
下面的例子使用has方法隐藏某些属性 , 不被in运算符发现 。
JavaScript Proxy基本知识梳理

文章插图
 
上面代码中 , 如果原对象的属性名的第一个字符是下划线 , proxy.has就会返回false , 从而不会被in运算符发现 。
如果原对象不可配置或者禁止扩展 , 这时has拦截会报错 。
JavaScript Proxy基本知识梳理

文章插图
 
上面代码中 , obj对象禁止扩展 , 结果使用has拦截就会报错 。也就是说 , 如果某个属性不可配置(或者目标对象不可扩展) , 则has方法就不得“隐藏”(即返回false)目标对象的该属性 。
值得注意的是 , has方法拦截的是HasProperty操作 , 而不是HasOwnProperty操作 , 即has方法不判断一个属性是对象自身的属性 , 还是继承的属性 。
另外 , 虽然for...in循环也用到了in运算符 , 但是has拦截对for...in循环不生效 。
JavaScript Proxy基本知识梳理

文章插图
 
上面代码中 , has拦截只对in运算符生效 , 对for...in循环不生效 , 导致不符合要求的属性没有被for...in循环所排除 。
construct()
construct方法用于拦截new命令 , 下面是拦截对象的写法 。
JavaScript Proxy基本知识梳理

文章插图
 
construct方法可以接受两个参数 。
  • target:目标对象
  • args:构造函数的参数对象
  • newTarget:创造实例对象时 , new命令作用的构造函数(下面例子的p)

JavaScript Proxy基本知识梳理

文章插图
 
construct方法返回的必须是一个对象 , 否则会报错 。
JavaScript Proxy基本知识梳理

文章插图
 
deleteProperty()
deleteProperty方法用于拦截delete操作 , 如果这个方法抛出错误或者返回false , 当前属性就无法被delete命令删除 。
JavaScript Proxy基本知识梳理

文章插图
 
上面代码中 , deleteProperty方法拦截了delete操作符 , 删除第一个字符为下划线的属性会报错 。
注意 , 目标对象自身的不可配置(configurable)的属性 , 不能被deleteProperty方法删除 , 否则报错 。


推荐阅读