Proxy在目标对象之前架设一层拦截,外部所有的访问都必须先通过这层拦截,因此提供了一种机制,可以对外部的访问进行过滤和修改。
ES6原生提供了Proxy构造函数,用来生成Proxy实例。下面代码中proxy代理target。
var proxy = new Proxy(target, handler);
Proxy对象的所有用法,都是上面的这种形式。不同的只是handle参数的写法。其中new Proxy用来生成Proxy实例,target是表示所要拦截的对象,handle是用来定制拦截行为的对象。
var proxy = new Proxy({}, { get: function(target, property) { return 35; } }); proxy.time // 35 proxy.name // 35 proxy.title // 35
上面是一个拦截读取属性的行为的例子。要使Proxy起作用,必须针对Proxy实例进行操作,而不是针对目标对象(target)进行操作。如果handler没有设置任何拦截,那就等同于直接通向原对象,如下:
var target = {}; var handler = {}; var proxy = new Proxy(target, handler); proxy.a = 'b'; target.a // "b"
Proxy对象也可以作为其它对象的原型对象。下面代码中,proxy对象是obj的原型对象,obj本身并没有time属性,所以根据原型链,会在proxy对象上读取属性,从而被拦截。
var proxy = new Proxy({}, { get: function(target, property) { return 35; } }); let obj = Object.create(proxy); obj.time // 35
get(target, propKey, receiver) set(target, propKey, value, receiver) has(target, propKey) deleteProperty(target, propKey) ownKeys(target) getownPropertyDescriptor(target, propKey) defineProperty(target, propKey, propDesc) preventExtensions(target) getPrototypeOf(target) isExtensible(target) setPrototypeOf(target, proto) apply(target, object, args) construct(target, args)
get()
get方法用于拦截某个属性的读取操作,可以接收三个参数,依次为目标对象,属性名和Proxy实例本身,其中最后一个参数可选。
下面代码表示如果有这个属性则返回属性值,如没有就会输出111,如果没有这个拦截,没有属性会返回undefined。
var person = { name: "张三" }; var proxy = new Proxy(person, { get: function(target, property) { if (property in target) { return target[property]; } else { console.log(111) } } }); proxy.name // "张三" proxy.age // 111
set()
set方法用来拦截某个属性的赋值操作,可以接受4个参数,依次为目标对象,属性名,属性值和Proxy实例本身,其中最后一个参数可选。
假设Person对象有个age属性,该属性是一个不大于200的整数,那么可以使用Proxy来保证age的属性值符合要求。
let validator = { set: function(obj, prop, value) { if (prop === 'age') { if (!Number.isInteger(value)) { throw new TypeError('The age is not an integer'); // 报错1 } if (value > 200) { throw new RangeError('The age seems invalid'); //报错2 } } // 对于满足条件的 age 属性以及其他属性,直接保存 obj[prop] = value; } }; let person = new Proxy({}, validator); person.age = 100; person.age // 100 person.age = 'young' // 报错1 person.age = 300 // 报错2
const handler = { set: function(obj, prop, value, receiver) { obj[prop] = receiver; } }; const proxy = new Proxy({}, handler); proxy.foo = 'bar'; proxy.foo === proxy // true
apply()
apply方法拦截函数的调用、call和apply操作。apply方法可以接收三个参数,依次是目标对象,目标对象的上下文对象(this)和目标对象的参数数组。
var target = function () { return 'I am the target'; }; var handler = { apply: function () { return 'I am the proxy'; } }; var p = new Proxy(target, handler); p() // "I am the proxy"
has()
has方法用来拦截Hasproperty操作,即判断对象是否有某个属性时,这个方法会生效。典型的操作就是in操作。has方法可以接收两个参数,分别是目标对象,需查询的属性名。
下面代码中,如原对象的属性名的第一个字符是下划线,则返回false。
var handler = { has (target, key) { if (key[0] === '_') { return false; } return key in target; } }; var target = { _prop: 'foo', prop: 'foo' }; var proxy = new Proxy(target, handler); '_prop' in proxy // false
var obj = { a: 10 }; Object.preventExtensions(obj); var p = new Proxy(obj, { has: function(target, prop) { return false; } }); 'a' in p // TypeError is thrown
has方法拦截的是hasProperty操作,而不是hasOwnProperty操作,即不判断一个属性是自身的属性还是继承属性。
has方法只对in运算符生效,而不对for...in循环生效,如下。
construct()
construct方法用于拦截new命令,下面是拦截对象的写法。construct方法可以接收三个参数,依次是目标对象,构造函数的参数对象和创造实例对象时,new命令作用的构造函数(可选)
var p = new Proxy(function () {}, { construct: function(target, args) { console.log('called: ' + args.join(', ')); return { value: args[0] * 10 }; } }); (new p(1)).value // "called: 1" // 10
var p = new Proxy(function() {}, { construct: function(target, argumentsList) { return 1; } }); new p() // 报错
deleteproperty()
deleteProperty方法拦截的是delete操作,如果这个方法抛出错误或返回false,则当前属性就无法被delete命令删除。
原文:https://www.cnblogs.com/kdcg/p/9145385.html
原文地址:https://www.cnblogs.com/xjy20170907/p/11558920.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。