ES6-Proxy

前言javascript

Proxy, 也就是代理。設計模式中有一種叫作代理模式,能夠用來實現AOP,攔截器。後端常常會用到。html

那什麼是代理模式,這樣說吧。快到5.20了你想追個妹子,惋惜沒她聯繫方式,恰好你朋友認識她,你就請你的朋友代理你,捎信給她,表訴你的愛慕之情。就有點像讀書那會的送情書。前端

代理在生活中很常見,董事長和助理之間是代理關係,你的領導和你之間也是代理,領導安排活,你就幹。領導 ~ 你 ~ 活,這三者之間,你就是屬於代理人,領導只管安排,而後你處理好,把結果給他看。是否是很簡單?java

 

開始進入正題es6

ES6 原生提供了 Proxy API , 用來生成 Proxy 實例。後端

那 Proxy 在前端有什麼用處呢設計模式

①、攔截和監視外部對對象的訪問閉包

②、下降函數或類的複雜度app

③、在複雜操做前對操做進行校驗或對所需資源進行管理函數

運用

1、如何使用 Proxy 

let proxy = new Proxy(target, handler);

target 參數表示須要攔截的目標對象。

handler 參數是一個對象,用來定製攔截行爲。

handler 支持 13 種攔截行爲,以下:

get(target, property, receiver)     //攔截對象屬性的讀取
set(target, property, value, receiver)    //攔截對象屬性的設置
has(target, property)    // 攔截 property in target 的操做,返回布爾值
deleteProperty(target, property) // 攔截 delete target[property] 的操做,返回布爾值
apply(target, context, args)   //攔截 Proxy實例做爲函數調用的操做
construct(target, args)  // 攔截 Proxy 實例做爲構造函數調用的操做
ownKeys(target)

//如下方法,分別攔截 Object對象 下對應的操做
//如 definedProperty 攔截 Object.defineProperty(proxy) 操做。
getOwnPropertyDescriptor(target, propKey)
defineProperty(target, propKey, propDesc)
preventExtensions(target)
isExtensible(target)
getPrototypeOf(target)
setPrototypeOf(target, proto)

Proxy 功能強大,咱們常常用到的是它的 get, set 方法。

舉個栗子,攔截某個對象的屬性讀寫。

let obj = {
    name: 'jk',
    age: 25
}

let handler = {
    get(target, property, receiver) {
        let value = target[property];
        console.log(`get ${property} value: ${value}`);
        return value;
    },
    set(target, property, value, receiver) {
        console.log(`set ${property} value: ${value}`)
    }
}

let proxy = new Proxy(obj, handler);

proxy.name 
// get name value: jk
// jk

proxy.age = 26;
// set name value: 26
// 26

2、Proxy的用處

有的童鞋就會問,Proxy 到底有什麼用處呢? 固然有用了,下面介紹下我能想到的用處。

① 實現 AOP

運用 Proxy 的 apply 方法。

咱們有時候但願 在函數執行以前,先運行某函數,函數執行以後,再運行某函數。

先定義幾個函數,後面會用到。

const log = (...args) => console.log(...args);

const test = () => log('test'); 
const beforeTest = () => log('beforeTest'); 
const afterTest = () => log('afterTest'); 

最基本的實現:

const testBetter = (cur, before, after) => {    
    before();
    cur();
    after();
}

testBetter(test, beforeTest, afterTest);

說實話,我以爲上面的代碼就能夠了,沒什麼很差。。。。。

固然也有其餘的方法:

以前沒有 Proxy 的作法是利用 閉包實現一個裝飾器模式,(ES7已實現 Decorator),以下:

Function.prototype.before = function(beforefn) {
    let _self = this;  //存儲 當前函數
    return function() {
        beforefn.apply(_self, arguments);
        return _self.apply(this, arguments);   
    }
}

Function.prototype.after = function(afterfn) {
    let _self = this; //存儲 當前函數
    return function() {
        var ret = _self.apply(this, arguments);
        afterfn.apply(this, arguments);
        return ret; 
    }
}

const testBetter = test.before(beforeTest).after(afterTest);

testBetter();
// beforeTest
// test
// afterTest

如今,咱們有了 Proxy, 就能夠更方便了。能夠運用 Proxy 的 apply 方法來實現。

const createProxy = (target, handler) => new Proxy(target, handler);
const createAop = (current, before, after) => {
    return createProxy(current, {
        apply(target, context, args) {
            before.call(context);
            Reflect.apply(...arguments);  // target.apply(context, args);
            after.call(context)
        }
    })
}
const testProxy = createAop(test, beforeTest, afterTest);
testProxy();
// beforeTest
// test
// afterTest

咱們能夠用 boforeTest 和 afterTest 來打印一些咱們調試所須要的信息,不就實現了一個簡單的日誌功能嗎。

②、咱們也能夠用 Proxy 的 get 來過濾數據。

let grade = {
    age: [4, 5, , undefined, 6, 7, ,null, 8, , 9, 10]
}

//去除undefined 和 null
let filterArr = (arr) => arr.filter(item => item !== undefined && item !== null);

let proxy = new Proxy(grade, {
    get(target, property, receiver) {
        let value = target[property];
        if ( Array.isArray(value) ) {
            return Reflect.apply(filterArr, window, [value]);
        }
    }
})

proxy.age;
// [4, 5, 6, 7, 8, 9, 10]

還能夠實現其餘的功能:攔截,數據校驗,私有屬性等等。

3、Proxy 如何取消。

Proxy.revocable方法返回一個可取消的 Proxy 實例。

let {proxy, revoke} = Proxy.revocable(target, handler);

 

文章只是敘述了 Proxy 的冰山一角,更多內容請移步個人參考連接。

今天先寫到這裏,若有錯誤之處,還望指出。謝謝。

 

參考

http://es6.ruanyifeng.com/#docs/proxy

https://www.w3cplus.com/javascript/use-cases-for-es6-proxies.html

曾探-JavaScript設計模式與開發實踐,P48

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息