能夠把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); } }); }
參考資料: