初探Vue3.0 中的一大亮点Proxy的使用(2)

let obj = {}; Object.defineProperty(obj, "a", { configurable: false, enumerable: false, value: 10, writable: false }); let proxy = new Proxy(obj,{ get : function (target,prop) { return 20; } }) console.log(proxy.a) // Uncaught TypeError

上述 obj 对象中的 a 属性不可写,不可配置,我们通过 Proxy 创建了一个 proxy 的实例,并拦截了它的 get 操作,当我们输出 proxy.a 时会抛出异常,此时,如果我们将 get 方法的返回值修改跟目标属性的值相同时,也就是 10 , 就可以消除异常~

--handler.set(target, property, value, receiver)

用于拦截设置属性值的操作,参数于 get 方法相比,多了一个 value ,即要设置的属性值~

在严格模式下,set方法需要返回一个布尔值,返回 true 代表此次设置属性成功了,如果返回false且设置属性操作失败,并且会抛出一个TypeError。

let proxy = new Proxy({},{ set : function (target,prop,value) { if( prop === 'count' ){ if( typeof value === 'number'){ console.log('success') target[prop] = value; }else{ throw new Error('The variable is not an integer') } } } }) proxy.count = '10'; // The variable is not an integer proxy.count = 10; // success

上述我们通过修改 set方法,对 目标对象中的 count 属性赋值做了限制,我们要求 count 属性赋值必须是一个 number 类型的数据,如果不是,就返回一个错误 The variable is not an integer,我们第一次为 count 赋值字符串 '10' , 抛出异常,第二次赋值为数字 10 , 打印成功,因此,我们可以用 set 方法来做一些数据校验!

同样,如果目标属性是不可写及不可配置的,则不能改变它的值,即赋值无效,如下:

let obj = {}; Object.defineProperty(obj, "count", { configurable: false, enumerable: false, value: 10, writable: false }); let proxy = new Proxy(obj,{ set : function (target,prop,value) { target[prop] = 20; } }) proxy.count = 20 ; console.log(proxy.count) // 10

上述 obj 对象中的 count 属性,我们设置它不可被修改,并且默认值,我们给定为 10 ,那么即使给其赋值为 20 ,结果仍旧没有变化!

--handler.apply(target, thisArg, argumentsList)

用于拦截函数的调用,共有三个参数,分别是目标对象(函数)target,被调用时的上下文对象 thisArg 以及被调用时的参数数组 argumentsList,该方法可以返回任何值。

target 必须是是一个函数对象,否则将抛出一个TypeError;

function sum(a, b) { return a + b; } const handler = { apply: function(target, thisArg, argumentsList) { console.log(`Calculate sum: ${argumentsList}`); return target(argumentsList[0], argumentsList[1]) * 10; } }; let proxy = new Proxy(sum, handler); console.log(sum(1, 2)); // 3 console.log(proxy(1, 2)); // Calculate sum:1,2 // 6

实际上,apply 还会拦截目标对象的 Function.prototype.apply() 和 Function.prototype.call(),以及 Reflect.apply() 操作,如下:

console.log(proxy.call(null, 3, 4)); // Calculate sum:3,4 // 14 console.log(Reflect.apply(proxy, null, [5, 6])); // Calculate sum: 5,6 // 22

--handler.construct(target, argumentsList, newTarget)

construct 用于拦截 new 操作符,为了使 new 操作符在生成的 Proxy对象上生效,用于初始化代理的目标对象自身必须具有[[Construct]]内部方法;它接收三个参数,目标对象 target ,构造函数参数列表 argumentsList 以及最初实例对象时,new 命令作用的构造函数,即下面例子中的 p。

let p = new Proxy(function() {}, { construct: function(target, argumentsList, newTarget) { console.log(newTarget === p ); // true console.log('called: ' + argumentsList.join(', ')); // called:1,2 return { value: ( argumentsList[0] + argumentsList[1] )* 10 }; } }); console.log(new p(1,2).value); // 30

另外,该方法必须返回一个对象,否则会抛出异常!

var p = new Proxy(function() {}, { construct: function(target, argumentsList, newTarget) { return 2 } }); console.log(new p(1,2)); // Uncaught TypeError

--handler.has(target,prop)

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

转载注明出处:http://www.heiqu.com/651450e6e9ccce3dcc5edf558af7fe92.html