Vue中的代理Proxy和$ref (3)

15 console.log(target.count); // => 1 // 你可以为 name 赋一个非数值类型的值,因为该属性已经存在

16 proxy.name = "proxy";

17 console.log(proxy.name); // => "proxy"

18 console.log(target.name); // => "proxy"

// 抛出错误 proxy.anotherName = "proxy";

这段代码定义了一个代理来验证添加到target的新属性,当执行proxy.count=1时,set陷阱被调用,此时trapTarget的值等于targetkey等于"count"value等于1receiver等于proxy

由于target上没有count属性,因此代理继续将value值传入isNaN(),如果结果是NaN,则证明传入的属性值不是数字,同时也抛出一个错误。在这段代码中,count被设置为1,所以代理调用Reflect.set()方法并传入陷阱接受的4个参数来添加新属性。

proxy.name可以成功被赋值为一个字符串,这是因为target已经拥有一个name属性,但通过调用trapTarget.hasownproperty()方法验证检查后被排除了,所以目标已有的非数字属性仍然可以被操作。

然而,将proxy.anotherName赋值为一个字符串时会抛出错误。目标上没有anotherName属性,所以它的值需要被验证,而由于"Proxy"不是一个数字值,因此抛出错误。

set代理陷阱可以拦截写入属性的操作,get代理陷阱可以拦截读取属性的操作

用get陷阱验证对象结构(Object Shape)

JS有一个时常令人感到困惑的特殊行为,即读取不存在的属性时不会抛出错误,而是用undefined代替被读取属性的值。

1 //get陷阱验证对象结构(Object Shape)

2 let target = {};

3 console.log(target.name); // => undefined

对象结构是指对象中所有可用属性和方法的集合,JS引擎通过对象结构来优化代码,通常会创建类来表示对象,如果可以安全地假定一个对象将始终具有相同的属性和方法,那么当程序试图访问不存在的属性时会抛出错误。代理让对象结构检验变得简单。

 

因为只有当读取属性时才会检验属性,所以无论对象中是否存在某个属性,都可以通过get陷阱来检测,它接受3个参数:

 

trapTarget 被读取属性的源对象(代理的目标)

key 要读取的属性键(字符串或Symbol)

receiver 操作发生的对象(通常是代理)

由于get陷阱不写入值,所以它复刻了set陷阱中除value外的其他3个参数,Reflect.get()也接受同样3个参数并返回属性的默认值。

 

如果属性在目标上不存在,则使用get陷阱和Reflect.get()时会抛出错误:

 

 

let proxy = new Proxy({}, {

    get(trapTarget, key, receiver) {

        if (!(key in receiver)) {

            throw new TypeError("Property " + key + " doesn't exist.");

        }

        return Reflect.get(trapTarget, key, receiver);

    }

});

// 添加属性的功能正常

proxy.name = "proxy";

console.log(proxy.name); // => "proxy"

// 读取不存在属性会抛出错误

console.log(proxy.nme); // => 抛出错误

 

 

 

原型代理陷阱

Object.setPrototypeOf()方法被用于作为ES5中的Object.getPrototypeOf()方法的补充。通过代理中的setPrototypeOf陷阱和getPrototypeOf陷阱可以拦截这两个方法的执行过程,在这两种情况下,Object上的方法会调用代理中的同名陷阱来改变方法的行为。

两个陷阱均与代理有关,但具体到方法只与每个陷阱的类型有关,setPrototypeOf陷阱接受以下这些参数:

trapTarget 接受原型设置的对象(代理的目标)

proto 作为原型使用的对象

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zypwgx.html