首頁  >  文章  >  web前端  >  ES6中的Proxy是什麼? Proxy的詳細分析

ES6中的Proxy是什麼? Proxy的詳細分析

不言
不言原創
2018-09-27 16:21:393500瀏覽

這篇文章帶給大家的內容是關於ES6中的Proxy是什麼? Proxy的詳細分析,有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

proxy的中文有代理的意思。在其他的程式設計語言中這個單字也具有類似的意思。

它是什麼

Proxy是一個建構器。在js中建構器的典型特點就是首字母大寫,我們透過new Proxy(原始物件,{代理列表})格式去創建物件,創建的這個物件我們稱之為代理物件。
即:

代理對象= new Proxy(原始對象,{代理列表})

之所以要額外產生這麼一個代理對象,好處在於可以保持原對像不變,在代理物件中加入新的功能,或是改造某些功能。而這個原對象則可以在適當的時機回滾回去。可與設計模式中的代理模式對比理解。

使用格式

var obj;
var proxyObj = new Proxy(obj, {
    对obj的操作1: 函数1,
    对obj的操作2: 函数2,
    ...
    
})

入門範例

Proxy的基本示範

var obj = {name:'fan',age:34}
console.info(obj.name)

var proxyObj = new Proxy(obj,{
    get:function(target,key,receiver){console.info(target,key,receiver); return 'no'}
})

console.info(proxyObj.name) 
console.info(proxyObj.abc)

解釋如下:

  • proxxy物件是在obj物件的基礎之上創建的一個新物件。

  • proxyObj.name是要去取得proxy物件的name屬性。 .操作符會自動去呼叫get()方法。這一點非常重要,在js中,物件是屬性的無序集合。物件只有屬性,其他什麼都沒有. 而我們常說的呼叫物件的某個方法:例如陣列物件arr的sort方法:arr.sort(),這裡的sort也是arr物件的屬性(更嚴謹一點,sort是arr.__proto__這個物件的屬性),與length屬性相比,sort屬性的屬性值是一個函數,所以在它的後面加()來執行這個函數,而length屬性的值是一個數值,所以不需要加()就可以直接使用。再次強調一下:物件的.操作,會自動去呼叫get。當然,我們平時使用.操作時,是沒有感知到這一點的。

  • 在new Proxy的第二個參數中,明確設定了get的方法:當存取proxyObj的任意屬性時,輸出target,key,receiver的值,並統一傳回no 。所以proxyObj.name和proxyObj.abc都會得到no。

寫到這裡你會覺得原始物件與代理物件之間有什麼關係呢?為什麼叫代理呢?

理解代理程式的作用

代理物件可以理解為明星的經紀人。

外界 <----> 原对象;
外界 <----> 代理对象 <------> 原对象;

也以上面的程式碼為例,改進一下需求:如果有人問obj的名字,就直接告訴對方; 如果有人問obj的年齡,就回傳小5歲的年齡。

var obj = {name:'fan',age:34}
console.info(obj.age)           // 34
var proxyObj = new Proxy(obj,{
    get:function(target,key,receiver){
        console.info(target === obj);           //true
        console.info(receiver === proxyObj);    //true
        if('age' === key){
            return target[key] - 5;
        }
        else{
            return target[key]
        }
    }
})

console.info(proxyObj.age)  // 34- 5 = 29

解釋如下:

  • get函數中的三個參數:target,key,receiver。 target就是原物件j,keys是目前的屬性名稱;receiver是代理物件。你可以在get方法中做任意的自訂的處理。

代理物件與原始物件的關係

var arr = [2,1]
var proxyArr = new Proxy(arr,{} )
proxyArr.push(3);
console.info(arr) // [2,1,3]
console.info(arr === proxyArr) // false
arr.sort();
console.info(proxyArr[0]) // 1

以上程式碼中,這個代理物件並沒有做任何的特殊操作。理解為明星的經理人消極怠工:原封不動地轉告外界的訊息給明星本身。所以在proxyArr上做到操作會直接影響到arr上。

同理,在arr上的操作,也會影響proxyArr。
但要注意:proxyArr與arr是兩個不同的物件:arr !== proxyArr。

你可能會想一想:為什麼proxyArr能夠直接使用push這個方法呢?原因是:

proxyArr.__proto__ === arr.__proto__ === Array.prototype

前一個等式成立的原因是由new Proxy的基因決定的:原始物件被代理了嘛。

代理程式清單

在new Proxy的第二個參數中,可以設定的代理屬性如下:

var proxyObj = new Proxy(obj, {

    get: function(tagert,key,receiver){},
    set: function(tagert,key,receiver){},
    has: function(tagert,key){},
    deleteProperty: function(tagert,key){},
    ownKeys: function(tagert){},
    getOwnPropertyDescriptor: function(tagert,key){},
    defineProperty: function(tagert,key,desc){},
    preventExtensions: function(tagert){},
    getPrototypeOf: function(tagert){},
    isExtensible: function(tagert){},
    setPrototypeof: function(tagert,proto){},
    apply: function(tagert,obj,args){},
    construct: function(tagert,args){},
    
})

get() 代理程式的應用

允許陣列下標是負值

在js中,陣列的有效下表是從0開始的。

var arr = [1,2,3];
console.info(arr[0])  // 1
console.info(arr[-1]) // undefined
console.info(arr[100]) // undefined

值得注意的是,下表越界或是負值的情況下,得到的結果是undefined,而不是報錯。

下面我們希望陣列可以取負值下表,規則如下:

  • -n表示倒數第n個元素。例如:-1表示倒數第一個元素。

使用Proxy解決如下:

var arr = [1,2,3];

var proxyArr = new Proxy(arr,{
    get: (target,prop)=>{
        let index = Number(prop);
        if(index < 0){
            prop = target.length + index;
        }
        return target[prop];
        
    }
})
console.info(arr[-1]);      // undefined
console.info(proxyArr[-1]); // 3

注意:

  • Number()可以把傳入的值轉成數值型。非數值 --> NaN;

  • 如果是proxyArr.push(3),由於此時的prop是'push',所以不會進入if分支。

  • 如果是proxyArr[-1],此時的prop是'-1',所以會進入到if分支:把prop從-1改成2 ,從而實現了被代理的效果。

  • 此時,完全可以把proxyArr當作一個陣列來使用,sort,push等方法都可以呼叫。 Array.isArray(proxyArr) === true

  • 當然,你也可以進一步封裝成工廠函數。

    function myArr(...args){
        var arr = new Array(...args);
    
        var proxyArr = new Proxy(arr,{
            get: (target,key)=>{
                let index = Number(key);
                if(index < 0){
                    key = target.length + index;
                }
                return target[key];
    
            }
        })
        return proxyArr;
    }
    var obj = myArr([1,2,3]);
    console.info(obj[0],obj[-1])

    鍊式運算

    var double = n => n*2;
    var pow2 = n => n*n;
    var half = n => n/ 2;
    var add1 = n => n+1;
    
    function pipe (num){
        let funs = []
        let obj = new Proxy({},{
            get:function(target,prop){
                if(prop === 'end'){
                    return funs.reduce((val,currentfn)=>currentfn(val),num);
                }else{
                    funs.push(window[prop])
                }
                return obj;
            }
        })
    
        return obj;
    };
    
    console.info( pipe(4).double.pow2.end);
    console.info( pipe(4).pow.double.pow2.add1.end);

    以上是ES6中的Proxy是什麼? Proxy的詳細分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn