Proxy的使用

一、Proxy概述

Proxy用于修改默寫操作的默認(rèn)行為,等同于在語言層面作出修改,所以屬于一種“元編程語言”,既對編程語言進(jìn)行編程。
對于Proxy,我相信大家都非常熟悉了,尤其是對于使用Vue開發(fā)的人來說。雖然大家知道,我這里還是要說一下(多一點字?jǐn)?shù)嗎,哈哈)。說白了,Proxy可以理解成在目標(biāo)對象前架設(shè)一“攔截”層,而外界對該對象訪問的時候都必須經(jīng)過該層攔截,類似過濾器一樣的機(jī)制。Proxy的詞意是代碼,既是代理默寫操作,亦可以理解為“代理器”。
而說到對象攔截器,就不得不說Object.definePropery這個函數(shù),也正是這個屬性,面試中難倒了一大堆同學(xué)。Object.definePropery也有攔截對象的作用,而且只能劫持對象的屬性,對于數(shù)組而言,就需要其他的方式進(jìn)行處理才能實現(xiàn)攔截的作用。而且對于對象的對象,是需要經(jīng)過層層遍歷才可以實現(xiàn)攔截。這是因為這樣,所以才有了Proxy的出現(xiàn),對于Proxy,它是可以完整的劫持整個對象,并且Proxy的有多達(dá)13種劫持操作,因為這些優(yōu)勢,自然而然的,Proxy成了劫持對象的首選。

二、使用

Proxy的第一個P大寫,而我們平時寫的構(gòu)造函數(shù)也是大寫,這就不免讓我們認(rèn)為Proxy是一個構(gòu)造函數(shù)。

var target = {};
var handler = {
    get: function(target, property) {
        return 23;
    }
};
var proxy = new Proxy(target, handler);
console.log(proxy.name); // 23

上面的proxy.name,最終輸出23,證明我們的猜想是正確的,Proxy確實是一個構(gòu)造函數(shù),后來查資料知道了es6原生提供Proxy構(gòu)造函數(shù),用于生成Proxy實例,而且它用法參數(shù)也正如上面寫的一樣,對一個參數(shù)為目標(biāo)對象,而第二個參數(shù)handler,正是我們定義攔擊對象的方法定義。

三、Proxy實例的方法

前面說到了Pxoxy有多達(dá)13種攔截操作,也正是這里所說的實例的方法,下面是Pxoxy實例方法一覽。

get(target, propkey, reveiver)
攔截對象屬性的讀取,如上面的proxy.name,返回類型不限。最后一個參數(shù)receiver屬性很少用到,一般沒用傳遞,它的大致是當(dāng)target對象設(shè)置了propkey屬性的get函時,reveiver對象會綁定get函數(shù)的this對象。
1.set(target, propkey, value, receiver)
攔截對象屬性的設(shè)置,既如我們的proxy.name = 'june'一樣。
2.has(target, propkey)
攔截propkey in proxy的操作,返回一個布爾值。
3.deleteProperty(target, propkey)
攔截delete proxy([propkey])的操作,返回一個布爾值。
4.enumerate(target)
攔截for(var x in proxy),返回一個遍歷器
5.hasOwn(target, propkey)
攔截proxy.hasOwnProperty('name'),返回一個布爾值。
6.ownkeys(target)
攔截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy),返回一個數(shù)組。該方法返回對象所有的自身的屬性,而Object.keys()僅返回對象可遍歷的屬性。
7.getOwnPropertyDescriptor(target, propkey)
攔截Object.getOwnPropertyDescriptor(target,propkey),返回屬性的描述對象。
8.defineProperty(target,propkey,propDesc)
攔截Object.defineProperty(target,propkey,propDesc)、Object.definePropertys(target,propkey,propDesc),返回一個布爾值。
9.preventExtensions(target)
攔截Object.preventExtensions(target),返回一個對象。
10.isExtensible(target)
攔截Object.isExtensible(proxy),返回一個布爾值。
11.setPrototypeOf(target,proto)
攔截Object.setPrototypeOf(proxy,proto),返回一個布爾值。如果目標(biāo)函數(shù)是對象,那么還有兩種操作可以攔截。
12.apply(target,object,args)
攔截Proxy實例作為函數(shù)調(diào)用的操作。
13.construct(target,args,proxy)
攔截Proxy實例作為構(gòu)造函數(shù)調(diào)用的操作。

以上便是Proxy13種實例方法。
而我這里將會例舉一些我們常用的方法出來,比如get,set等。

var target = {};
var handler = {
    get: function(target, propkey) {
        if(propkey in target) {
            return target[propkey]
        } else {
            throw new ReferenceError(`${propkey} does not exist`);
        }
    },
    set: function(target, propkey, value) {
        console.log(`target 對象下的propkey 值是 ${value}`);
        target[propkey] = value;
    },
    construct: function(target, args) {
        console.log(`called; ${args.join(',')}`);
    },
    apply: function() {
        console.log('調(diào)用了apply');
        return 'proxy';
    }
}
var proxy = new Proxy(target, handler);
proxy.name = 'june';
proxy.age = 10;
console.log(proxy.name);

輸入結(jié)果如下

target 對象下的propkey 值是 june
target 對象下的propkey 值是 10
june

而當(dāng)我們將target改成如下的時候

var target = function(a, b) {
    return a+b;
}
var proxy = new Proxy(target, handler);
console.log(proxy(10, 20));

輸入結(jié)果為

調(diào)用了apply
proxy

而當(dāng)我們把target定義為一個無返回函數(shù)時,就會打出我們construct函數(shù)里面打印的數(shù)據(jù)。
在這些函數(shù)里,只要我們對target對象做相應(yīng)的修改,就會起到攔截作用。其他攔截方法大同小異,在這里就不一一舉例了。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容