日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

概述

Proxy 用于修改某些操作的默認(rèn)行為,等同于在語(yǔ)言層面做出修改,所以屬于一種“元編程”(meta programming),即對(duì)編程語(yǔ)言進(jìn)行編程。

Proxy 可以理解成,在目標(biāo)對(duì)象之前架設(shè)一層“攔截”,外界對(duì)該對(duì)象的訪問(wèn),都必須先通過(guò)這層攔截,因此提供了一種機(jī)制,可以對(duì)外界的訪問(wèn)進(jìn)行過(guò)濾和改寫。Proxy 這個(gè)詞的原意是代理,用在這里表示由它來(lái)“代理”某些操作,可以譯為“代理器”。

JavaScript Proxy基本知識(shí)梳理

 

上面代碼對(duì)一個(gè)空對(duì)象架設(shè)了一層攔截,重定義了屬性的讀取(get)和設(shè)置(set)行為。這里暫時(shí)先不解釋具體的語(yǔ)法,只看運(yùn)行結(jié)果。對(duì)設(shè)置了攔截行為的對(duì)象obj,去讀寫它的屬性,就會(huì)得到下面的結(jié)果。

JavaScript Proxy基本知識(shí)梳理

 

上面代碼說(shuō)明,Proxy 實(shí)際上重載(overload)了點(diǎn)運(yùn)算符,即用自己的定義覆蓋了語(yǔ)言的原始定義。

ES6 原生提供 Proxy 構(gòu)造函數(shù),用來(lái)生成 Proxy 實(shí)例。

var proxy = new Proxy(target, handler);

Proxy 對(duì)象的所有用法,都是上面這種形式,不同的只是handler參數(shù)的寫法。其中,new Proxy()表示生成一個(gè)Proxy實(shí)例,target參數(shù)表示所要攔截的目標(biāo)對(duì)象,handler參數(shù)也是一個(gè)對(duì)象,用來(lái)定制攔截行為

JavaScript Proxy基本知識(shí)梳理

 

上面代碼中,作為構(gòu)造函數(shù),Proxy接受兩個(gè)參數(shù)。第一個(gè)參數(shù)是所要代理的目標(biāo)對(duì)象(上例是一個(gè)空對(duì)象),即如果沒(méi)有Proxy的介入,操作原來(lái)要訪問(wèn)的就是這個(gè)對(duì)象;第二個(gè)參數(shù)是一個(gè)配置對(duì)象,對(duì)于每一個(gè)被代理的操作,需要提供一個(gè)對(duì)應(yīng)的處理函數(shù),該函數(shù)將攔截對(duì)應(yīng)的操作。比如,上面代碼中,配置對(duì)象有一個(gè)get方法,用來(lái)攔截對(duì)目標(biāo)對(duì)象屬性的訪問(wèn)請(qǐng)求。get方法的兩個(gè)參數(shù)分別是目標(biāo)對(duì)象和所要訪問(wèn)的屬性。可以看到,由于攔截函數(shù)總是返回35,所以訪問(wèn)任何屬性都得到35。

注意,要使得Proxy起作用,必須針對(duì)Proxy實(shí)例(上例是proxy對(duì)象)進(jìn)行操作,而不是針對(duì)目標(biāo)對(duì)象(上例是空對(duì)象)進(jìn)行操作。

如果handler沒(méi)有設(shè)置任何攔截,那就等同于直接通向原對(duì)象。

JavaScript Proxy基本知識(shí)梳理

 

上面代碼中,handler是一個(gè)空對(duì)象,沒(méi)有任何攔截效果,訪問(wèn)proxy就等同于訪問(wèn)target。

Proxy 實(shí)例也可以作為其他對(duì)象的原型對(duì)象。

JavaScript Proxy基本知識(shí)梳理

 

上面代碼中,proxy對(duì)象是obj對(duì)象的原型,obj對(duì)象本身并沒(méi)有time屬性,所以根據(jù)原型鏈,會(huì)在proxy對(duì)象上讀取該屬性,導(dǎo)致被攔截。同一個(gè)攔截器函數(shù),可以設(shè)置攔截多個(gè)操作。

JavaScript Proxy基本知識(shí)梳理

 

對(duì)于可以設(shè)置、但沒(méi)有設(shè)置攔截的操作,則直接落在目標(biāo)對(duì)象上,按照原先的方式產(chǎn)生結(jié)果。

下面是 Proxy 支持的攔截操作一覽,一共 13 種。

JavaScript Proxy基本知識(shí)梳理

 

Proxy 實(shí)例的方法

下面是上面這些攔截方法的詳細(xì)介紹。

get()

get方法用于攔截某個(gè)屬性的讀取操作,可以接受三個(gè)參數(shù),依次為目標(biāo)對(duì)象、屬性名和 proxy 實(shí)例本身(嚴(yán)格地說(shuō),是操作行為所針對(duì)的對(duì)象),其中最后一個(gè)參數(shù)可選。

get方法的用法,上文已經(jīng)有一個(gè)例子,下面是另一個(gè)攔截讀取操作的例子。

JavaScript Proxy基本知識(shí)梳理

 

上面代碼表示,如果訪問(wèn)目標(biāo)對(duì)象不存在的屬性,會(huì)拋出一個(gè)錯(cuò)誤。如果沒(méi)有這個(gè)攔截函數(shù),訪問(wèn)不存在的屬性,只會(huì)返回undefined。

get方法可以繼承。

JavaScript Proxy基本知識(shí)梳理

 

上面代碼中,攔截操作定義在Prototype對(duì)象上面,所以如果讀取obj對(duì)象繼承的屬性時(shí),攔截會(huì)生效。

下面的例子使用get攔截,實(shí)現(xiàn)數(shù)組讀取負(fù)數(shù)的索引。

JavaScript Proxy基本知識(shí)梳理

 

上面代碼中,數(shù)組的位置參數(shù)是-1,就會(huì)輸出數(shù)組的倒數(shù)第一個(gè)成員。

利用 Proxy,可以將讀取屬性的操作(get),轉(zhuǎn)變?yōu)閳?zhí)行某個(gè)函數(shù),從而實(shí)現(xiàn)屬性的鏈?zhǔn)讲僮鳌?/p>JavaScript Proxy基本知識(shí)梳理

 

上面代碼設(shè)置 Proxy 以后,達(dá)到了將函數(shù)名鏈?zhǔn)绞褂玫男Ч?/p>

下面的例子則是利用get攔截,實(shí)現(xiàn)一個(gè)生成各種 DOM 節(jié)點(diǎn)的通用函數(shù)dom。

JavaScript Proxy基本知識(shí)梳理

 

下面是一個(gè)get方法的第三個(gè)參數(shù)的例子,它總是指向原始的讀操作所在的那個(gè)對(duì)象,一般情況下就是 Proxy 實(shí)例。

JavaScript Proxy基本知識(shí)梳理

 

上面代碼中,proxy對(duì)象的getReceiver屬性是由proxy對(duì)象提供的,所以receiver指向proxy對(duì)象。

JavaScript Proxy基本知識(shí)梳理

 


JavaScript Proxy基本知識(shí)梳理

 

上面代碼中,d對(duì)象本身沒(méi)有a屬性,所以讀取d.a的時(shí)候,會(huì)去d的原型proxy對(duì)象找。這時(shí),receiver就指向d,代表原始的讀操作所在的那個(gè)對(duì)象。

如果一個(gè)屬性不可配置(configurable)且不可寫(writable),則 Proxy 不能修改該屬性,否則通過(guò) Proxy 對(duì)象訪問(wèn)該屬性會(huì)報(bào)錯(cuò)。

JavaScript Proxy基本知識(shí)梳理

 

改一下就可以讀到屬性了

 

set()

set方法用來(lái)攔截某個(gè)屬性的賦值操作,可以接受四個(gè)參數(shù),依次為目標(biāo)對(duì)象、屬性名、屬性值和 Proxy 實(shí)例本身,其中最后一個(gè)參數(shù)可選。

假定Person對(duì)象有一個(gè)age屬性,該屬性應(yīng)該是一個(gè)不大于 200 的整數(shù),那么可以使用Proxy保證age的屬性值符合要求。

JavaScript Proxy基本知識(shí)梳理

 

上面代碼中,由于設(shè)置了存值函數(shù)set,任何不符合要求的age屬性賦值,都會(huì)拋出一個(gè)錯(cuò)誤,這是數(shù)據(jù)驗(yàn)證的一種實(shí)現(xiàn)方法。利用set方法,還可以數(shù)據(jù)綁定,即每當(dāng)對(duì)象發(fā)生變化時(shí),會(huì)自動(dòng)更新 DOM。

有時(shí),我們會(huì)在對(duì)象上面設(shè)置內(nèi)部屬性,屬性名的第一個(gè)字符使用下劃線開頭,表示這些屬性不應(yīng)該被外部使用。結(jié)合get和set方法,就可以做到防止這些內(nèi)部屬性被外部讀寫。

JavaScript Proxy基本知識(shí)梳理

 

上面代碼中,只要讀寫的屬性名的第一個(gè)字符是下劃線,一律拋錯(cuò),從而達(dá)到禁止讀寫內(nèi)部屬性的目的。

下面是set方法第四個(gè)參數(shù)的例子

JavaScript Proxy基本知識(shí)梳理

 

上面代碼中,set方法的第四個(gè)參數(shù)receiver,指的是原始的操作行為所在的那個(gè)對(duì)象,一般情況下是proxy實(shí)例本身,請(qǐng)看下面的例子。

JavaScript Proxy基本知識(shí)梳理

 

上面代碼中,設(shè)置myObj.foo屬性的值時(shí),myObj并沒(méi)有foo屬性,因此引擎會(huì)到myObj的原型鏈去找foo屬性。myObj的原型對(duì)象proxy是一個(gè) Proxy 實(shí)例,設(shè)置它的foo屬性會(huì)觸發(fā)set方法。這時(shí),第四個(gè)參數(shù)receiver就指向原始賦值行為所在的對(duì)象myObj。

注意,如果目標(biāo)對(duì)象自身的某個(gè)屬性,不可寫且不可配置,那么set方法將不起作用。

JavaScript Proxy基本知識(shí)梳理

 

上面代碼中,obj.foo屬性不可寫,Proxy 對(duì)這個(gè)屬性的set代理將不會(huì)生效。

注意,嚴(yán)格模式下,set代理如果沒(méi)有返回true,就會(huì)報(bào)錯(cuò)。

JavaScript Proxy基本知識(shí)梳理

 

上面代碼中,嚴(yán)格模式下,set代理返回false或者undefined,都會(huì)報(bào)錯(cuò)。

Apply()

apply方法攔截函數(shù)的調(diào)用、call和apply操作。

apply方法可以接受三個(gè)參數(shù),分別是目標(biāo)對(duì)象、目標(biāo)對(duì)象的上下文對(duì)象(this)和目標(biāo)對(duì)象的參數(shù)數(shù)組。

JavaScript Proxy基本知識(shí)梳理

 

下面是一個(gè)例子。

 

上面代碼中,變量p是 Proxy 的實(shí)例,當(dāng)它作為函數(shù)調(diào)用時(shí)(p()),就會(huì)被apply方法攔截,返回一個(gè)字符串。

下面是另外一個(gè)例子。

JavaScript Proxy基本知識(shí)梳理

 

上面代碼中,每當(dāng)執(zhí)行proxy函數(shù)(直接調(diào)用或call和apply調(diào)用),就會(huì)被apply方法攔截。

另外,直接調(diào)用Reflect.apply方法,也會(huì)被攔截。

JavaScript Proxy基本知識(shí)梳理

 

has()

has方法用來(lái)攔截HasProperty操作,即判斷對(duì)象是否具有某個(gè)屬性時(shí),這個(gè)方法會(huì)生效。典型的操作就是in運(yùn)算符。

has方法可以接受兩個(gè)參數(shù),分別是目標(biāo)對(duì)象、需查詢的屬性名。

下面的例子使用has方法隱藏某些屬性,不被in運(yùn)算符發(fā)現(xiàn)。

JavaScript Proxy基本知識(shí)梳理

 

上面代碼中,如果原對(duì)象的屬性名的第一個(gè)字符是下劃線,proxy.has就會(huì)返回false,從而不會(huì)被in運(yùn)算符發(fā)現(xiàn)。

如果原對(duì)象不可配置或者禁止擴(kuò)展,這時(shí)has攔截會(huì)報(bào)錯(cuò)。

JavaScript Proxy基本知識(shí)梳理

 

上面代碼中,obj對(duì)象禁止擴(kuò)展,結(jié)果使用has攔截就會(huì)報(bào)錯(cuò)。也就是說(shuō),如果某個(gè)屬性不可配置(或者目標(biāo)對(duì)象不可擴(kuò)展),則has方法就不得“隱藏”(即返回false)目標(biāo)對(duì)象的該屬性。

值得注意的是,has方法攔截的是HasProperty操作,而不是HasOwnProperty操作,即has方法不判斷一個(gè)屬性是對(duì)象自身的屬性,還是繼承的屬性。

另外,雖然for...in循環(huán)也用到了in運(yùn)算符,但是has攔截對(duì)for...in循環(huán)不生效。

JavaScript Proxy基本知識(shí)梳理

 

上面代碼中,has攔截只對(duì)in運(yùn)算符生效,對(duì)for...in循環(huán)不生效,導(dǎo)致不符合要求的屬性沒(méi)有被for...in循環(huán)所排除。

construct()

construct方法用于攔截new命令,下面是攔截對(duì)象的寫法。

JavaScript Proxy基本知識(shí)梳理

 

construct方法可以接受兩個(gè)參數(shù)。

  • target:目標(biāo)對(duì)象
  • args:構(gòu)造函數(shù)的參數(shù)對(duì)象
  • newTarget:創(chuàng)造實(shí)例對(duì)象時(shí),new命令作用的構(gòu)造函數(shù)(下面例子的p)
JavaScript Proxy基本知識(shí)梳理

 

construct方法返回的必須是一個(gè)對(duì)象,否則會(huì)報(bào)錯(cuò)。

JavaScript Proxy基本知識(shí)梳理

 

deleteProperty()

deleteProperty方法用于攔截delete操作,如果這個(gè)方法拋出錯(cuò)誤或者返回false,當(dāng)前屬性就無(wú)法被delete命令刪除。

JavaScript Proxy基本知識(shí)梳理

 

上面代碼中,deleteProperty方法攔截了delete操作符,刪除第一個(gè)字符為下劃線的屬性會(huì)報(bào)錯(cuò)。

注意,目標(biāo)對(duì)象自身的不可配置(configurable)的屬性,不能被deleteProperty方法刪除,否則報(bào)錯(cuò)。

defineProperty()

defineProperty方法攔截了Object.defineProperty操作。

JavaScript Proxy基本知識(shí)梳理

 

上面代碼中,defineProperty方法返回false,導(dǎo)致添加新屬性總是無(wú)效。

注意,如果目標(biāo)對(duì)象不可擴(kuò)展(non-extensible),則defineProperty不能增加目標(biāo)對(duì)象上不存在的屬性,否則會(huì)報(bào)錯(cuò)。另外,如果目標(biāo)對(duì)象的某個(gè)屬性不可寫(writable)或不可配置(configurable),則defineProperty方法不得改變這兩個(gè)設(shè)置。

getOwnPropertyDescriptor()

getOwnPropertyDescriptor方法攔截Object.getOwnPropertyDescriptor(),返回一個(gè)屬性描述對(duì)象或者undefined。

JavaScript Proxy基本知識(shí)梳理

 

上面代碼中,handler.getOwnPropertyDescriptor方法對(duì)于第一個(gè)字符為下劃線的屬性名會(huì)返回undefined。

getPrototypeOf()

getPrototypeOf方法主要用來(lái)攔截獲取對(duì)象原型。具體來(lái)說(shuō),攔截下面這些操作。

  • Object.prototype.__proto__
  • Object.prototype.isPrototypeOf()
  • Object.getPrototypeOf()
  • Reflect.getPrototypeOf()
  • instanceof

下面是一個(gè)例子。

JavaScript Proxy基本知識(shí)梳理

 

上面代碼中,getPrototypeOf方法攔截Object.getPrototypeOf(),返回proto對(duì)象。

注意,getPrototypeOf方法的返回值必須是對(duì)象或者null,否則報(bào)錯(cuò)。另外,如果目標(biāo)對(duì)象不可擴(kuò)展(non-extensible), getPrototypeOf方法必須返回目標(biāo)對(duì)象的原型對(duì)象。

isExtensible()

isExtensible方法攔截Object.isExtensible操作。

JavaScript Proxy基本知識(shí)梳理

 

ownKeys()

ownKeys方法用來(lái)攔截對(duì)象自身屬性的讀取操作。具體來(lái)說(shuō),攔截以下操作。

  • Object.getOwnPropertyNames()
  • Object.getOwnPropertySymbols()
  • Object.keys()
  • for...in循環(huán)

下面是攔截Object.keys()的例子。

JavaScript Proxy基本知識(shí)梳理

 

上面代碼攔截了對(duì)于target對(duì)象的Object.keys()操作,只返回a、b、c三個(gè)屬性之中的a屬性。

下面的例子是攔截第一個(gè)字符為下劃線的屬性名。

JavaScript Proxy基本知識(shí)梳理

 

注意,使用Object.keys方法時(shí),有三類屬性會(huì)被ownKeys方法自動(dòng)過(guò)濾,不會(huì)返回。

  • 目標(biāo)對(duì)象上不存在的屬性
  • 屬性名為 Symbol 值
  • 不可遍歷(enumerable)的屬性
JavaScript Proxy基本知識(shí)梳理

 

上面代碼中,ownKeys方法之中,顯式返回不存在的屬性(d)、Symbol 值(Symbol.for('secret'))、不可遍歷的屬性(key),結(jié)果都被自動(dòng)過(guò)濾掉。

ownKeys方法還可以攔截Object.getOwnPropertyNames()。

JavaScript Proxy基本知識(shí)梳理

 

for...in循環(huán)也受到ownKeys方法的攔截。

JavaScript Proxy基本知識(shí)梳理

 

上面代碼中,ownkeys指定只返回a和b屬性,由于obj沒(méi)有這兩個(gè)屬性,因此for...in循環(huán)不會(huì)有任何輸出。

ownKeys方法返回的數(shù)組成員,只能是字符串或 Symbol 值。如果有其他類型的值,或者返回的根本不是數(shù)組,就會(huì)報(bào)錯(cuò)。

JavaScript Proxy基本知識(shí)梳理

 

實(shí)例:Web 服務(wù)的客戶端

Proxy 對(duì)象可以攔截目標(biāo)對(duì)象的任意屬性,這使得它很合適用來(lái)寫 Web 服務(wù)的客戶端。

JavaScript Proxy基本知識(shí)梳理

 

同理,Proxy 也可以用來(lái)實(shí)現(xiàn)數(shù)據(jù)庫(kù)的 ORM 層

分享到:
標(biāo)簽:JavaScript Proxy
用戶無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定