能够把Proxy看做是一个拦截器,能够对目标对象的访问进行过滤和改写。proxy实例能够拦截对象的属性读取、赋值、删除、经过definedProperty定义等操做外,还能够拦截到对象被看成方法调用仍是构造函数使用等操做。那Proxy具体怎么用的呢?javascript
入门例子:给目标对象添加属性并赋值vue
var obj = new Proxy({}, { get: function (target, propKey, receiver) { console.log(`getting ${propKey} value: ${target[propKey]}!`); return Reflect.get(target, propKey, receiver); }, set: function (target, propKey, value, receiver) { console.log(`setting ${propKey} value: ${value}!`); return Reflect.set(target, propKey, value, receiver); } }); obj.count = 1 ++obj.count //setting count value: 1! //getting count value: 1! //setting count value: 2!
new Proxy(第一个参数, 第二个参数),第一个参数为目标对象,第二个参数为操做对象的行为的对象。java
Proxy构造函数的第一个参数为目标对象,和new出来的Proxy实例是同一个对象,但要注意只有修改Proxy实例值才会触发对应的拦截的方法:es6
var target = {}; var handler = {}; var proxy = new Proxy(target, handler); proxy.a = 'b'; target.a // "b"
Proxy实例也能够作为其余对象的原型对象:web
var proxy = new Proxy({}, { get: function(target, propKey) { return 35; } }); let obj = Object.create(proxy); obj.time // 35
能够设置多个拦截操做,例如:拦截对象做为方法使用、做为构造函数使用、做为对象操做属性等操做,能够在函数中return指定值:json
var handler = { get: function(target, name) { if (name === 'prototype') { return Object.prototype; } return 'Hello, ' + name; }, apply: function(target, thisBinding, args) { return args[0]; }, construct: function(target, args) { return {value: args[1]}; } }; var fproxy = new Proxy(function(x, y) { return x + y; }, handler); fproxy(1, 2) // 1 new fproxy(1, 2) // {value: 2} fproxy.prototype === Object.prototype // true fproxy.foo === "Hello, foo" // true
触发Proxy实例set的状况和触发Proxy实例get的状况:数组
var data = { odata: { name: 'odata', age: '21' }, arr: [{ name: 'youyi', age: '24' }], name: 'bb' } var obsever = new Proxy(data, { get: function (target, propKey, receiver) { console.log('get:', target[propKey]) return Reflect.get(target, propKey, receiver); }, set: function (target, propKey, value, receiver) { console.log('set:', value) return Reflect.set(target, propKey, value, receiver); } })
以上的结果:app
赋值却触发proxy实例get方法的状况
一、对proxy实例中的数组进行操做:函数
二、对proxy实例中的对象的属性进行操做:this
赋值触发proxy实例set方法:修改proxy实例的属性的整个值或新增一个属性并赋值时
一、修改proxy实例的数组类型属性
二、修改proxy实例的对象类型属性
var pipe = (function () { return function (value) { var funcStack = []; var oproxy = new Proxy({} , { get : function (pipeObject, fnName) { if (fnName === 'get') { return funcStack.reduce(function (val, fn) { return fn(val); },value); } funcStack.push(window[fnName]); return oproxy; } }); return oproxy; } }()); var double = n => n * 2; var pow = n => n * n; var reverseInt = n => n.toString().split("").reverse().join("") | 0; pipe(3).double.pow.reverseInt.get; // 63
const service = createWebService('http://example.com/data'); service.employees().then(json => { const employees = JSON.parse(json); // ··· }); function createWebService(baseUrl) { return new Proxy({}, { get(target, propKey, receiver) { return () => httpGet(baseUrl + '/' + propKey); } }); }
参考资料: