ECMAScript 6 笔记(15)- Proxy (1)

原创 乘风逐月 随笔 ES6 183阅读 2018-09-20 17:01:03 举报

一、概述

Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种 “元编程” ,即对编程语言进行编程。
Proxy 可以理解成,在目标对象之前架设一层 “拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。 Proxy 单词本意是 “代理”,在这里表示由它来 “代理” 某些操作,可以译为 “代理器”。

1.基本用法

ES6 原生提供 Proxy 构造函数,用来生成 Proxy 实例。

Proxy 对象的所有用法,都是上面这种形式,不同的只是 handler 参数的写法。target 表示所要拦截的目标对象,handler 是一个对象,用来定制拦截行为。
例如:

上例中,Proxy 构造函数接受了两个参数。第一个参数是所要代理的目标对象,是一个空对象。如果没有 Proxy 的介入,操作原来访问的就是这个对象。第二个参数是一个配置对象,对于每一个被代理的操作,需要提供一个对应的处理函数,该函数将拦截对应的操作。上例中,配置对象有一个 get 方法,用来拦截对目标对象属性的访问请求。get 方法的两个参数分别是目标对象和所要访问的属性,而拦截函数总是返回 35,所以访问任何属性都得到35。

2.注意

(1)要使 Proxy 起作用,必须针对 Proxy 实例进行操作,而不是针对目标对象进行操作。
(2)如果 handler 没有设置任何拦截,那就等同于直接通向原对象。

二、Proxy 实例的方法
1.get()

get 方法用于拦截某个属性的读取操作,可以接受三个参数,依次为目标对象、属性名和 Proxy 实例本身(严格说是操作行为所针对的对象),其中最后一个参数可选。
例如:

上例中,如果访问目标对象不存在的属性,会抛出一个错误。如果没有这个拦截函数,访问不存在的属性,只会返回 undefined。
get 方法可以继承

上例中,拦截操作定义在 Prototype 对象上,读取 obj 对象继承的属性时,拦截生效。

注: 如果目标对象自身的某个属性不可写且不可配置,则 Proxy 不能修改该属性,否则通过 Proxy 对象访问该属性会报错。

2.set()

set() 方法用来拦截某个属性的赋值操作,可以接受四个参数,依次为目标对象、属性名、属性值和 Proxy 实例本身,其中最后一个参数可选。
例如:一个 person 对象有一个 age 属性,要求该属性是不大于200的整数,使用 Proxy 保证 age 的属性值符合要求。

注:如果目标对象自身的某个属性不可写且不可配置,那么 set 方法将不起作用。

3.apply()

apply() 方法拦截函数的调用、call 和 apply 操作。
apply 方法可以接受三个参数,分别是目标对象、目标对象的上下文对象(this)和目标对象的参数数组

上例中,p 是 Proxy 的实例,当它作为函数调用时会被 apply 方法拦截。

4.has()

has 方法用来拦截 HasProperty 操作,即判断对象是否具有某个属性时,这个方法会生效。典型操作就是 in 运算符。
has 方法可以接受两个参数,分别是目标对象、需查询的属性名。
例如:

上例,使用 has 方法隐藏某些属性,不被 in 运算符发现。

注意
(1)对于不可配置或者禁止扩展的对象,使用 has 拦截会报错。
(2)has 方法拦截的是 HasProperty 操作,而不是 HasOwnProperty 操作,即 has 方法不判端一个属性是自身属性还是继承属性。
(3)for...in循环也用到了 in 运算符,但是 has 拦截对 for...in 循环不生效。

上例中,obj 禁止扩展,has 方法就不能“隐藏”目标对象的属性。

上例中,for...in 循环时,不符合要求的属性没有被排除。

5.construct()

construct 方法用于拦截 new 命令,该方法可以接受三个参数:目标对象,构造函数的参数对象,创造实例对象时,new 命令作用的构造函数(如下列中的 P)。
construct 方法返回的必须是一个对象,否则会报错。

6.deleteProperty()

deleteProperty 方法用于拦截 delete 操作,如果这个方法抛出错误或者返回 false,当前属性就无法被 delete 命令删除。

上例,不能删除第一个字符为下划线的属性。
注:目标对象自身的不可配置属性,不能被 deleteProperty 方法删除,否则报错。

评论 ( 0 )
最新评论
暂无评论

赶紧努力消灭 0 回复