摘要:在中構(gòu)造器的典型特點就是首字母大寫,我們通過原對象代理列表格式去創(chuàng)建對象創(chuàng)建的這個對象我們稱之為代理對象。就是原對象是當前的屬性名是代理對象。理解為明星的經(jīng)理人消極怠工原封不動地轉(zhuǎn)告外界的信息給明星本身。但是要注意與是兩個不同的對象。
ES6之Proxy
proxy的中文有代理的意思。在其他的程序設(shè)計語言中這個單詞也具有類似的含義。
它是什么Proxy是一個構(gòu)造器。在js中構(gòu)造器的典型特點就是首字母大寫,我們通過new Proxy(原對象,{代理列表})格式去創(chuàng)建對象,創(chuàng)建的這個對象我們稱之為代理對象。
即:
代理對象 = new Proxy(原對象,{代理列表})
之所以要額外產(chǎn)生這么一個代理對象,好處在于可以保持原對象不變,在代理對象中添加新的功能,或者是改造某些功能。而這個原對象則可以在適當?shù)臅r機回滾回去。可以與設(shè)計模式中的代理模式對比理解。
使用格式var obj; var proxyObj = new Proxy(obj, { 對obj的操作1: 函數(shù)1, 對obj的操作2: 函數(shù)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對象的基礎(chǔ)之上創(chuàng)建的一個新對象。
proxyObj.name是要去獲取proxy對象的name屬性。.操作符會自動去調(diào)用get()方法。這一點非常重要,在js中,對象是屬性的無序集合。對象只有屬性,其他什么都沒有. 而我們經(jīng)常說的調(diào)用對象的某個方法:例如數(shù)組對象arr的sort方法:arr.sort(),這里的sort也是arr對象的屬性(更嚴謹一點,sort是arr.__proto__這個對象的屬性),與length屬性相比,sort屬性的屬性值是一個函數(shù),所以在它的后面加()來執(zhí)行這個函數(shù),而length屬性的值是一個數(shù)值,所以不需要加()就可以直接使用。再次強調(diào)一下:對象的.操作,會自動去調(diào)用get。當然,我們平時使用.操作時,是沒有感知到這一點的。
在new Proxy的第二個參數(shù)中,明確設(shè)置了get的方法:當訪問proxyObj的任意屬性時,輸出target,key,receiver的值,并統(tǒng)一返回no。所以proxyObj.name和proxyObj.abc都會得到no。
寫到這里你會覺得原對象與代理對象之間有什么關(guān)系呢?為什么叫代理呢?
理解代理的作用代理對象可以理解為明星的經(jīng)紀人。
外界 <----> 原對象; 外界 <----> 代理對象 <------> 原對象;
還以上面的代碼為例,改進一下需求:如果有人問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函數(shù)中的三個參數(shù):target,key,receiver。 target就是原對象j,keys是當前的屬性名;receiver是代理對象。你可以在get方法中做任意的自定義的處理。
代理對象與原對象的關(guān)系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
以上代碼中,這個代理對象并沒有做任何的特殊操作。理解為明星的經(jīng)理人消極怠工:原封不動地轉(zhuǎn)告外界的信息給明星本身。所以在proxyArr上做到操作會直接影響到arr上。
同理,在arr上的操作,也會影響proxyArr。
但是要注意:proxyArr與arr是兩個不同的對象:arr !== proxyArr。
你可能會想一想:為什么proxyArr能夠直接使用push這個方法呢?原因是:
proxyArr.__proto__ === arr.__proto__ === Array.prototype
前一個等式成立的原因是由new Proxy的基因決定的:原對象被代理了嘛。
代理列表在new Proxy的第二個參數(shù)中,可以設(shè)置的代理屬性如下:
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() 代理的應(yīng)用 允許數(shù)組下標是負值
在js中,數(shù)組的有效下表是從0開始的。
var arr = [1,2,3]; console.info(arr[0]) // 1 console.info(arr[-1]) // undefined console.info(arr[100]) // undefined
值得注意的是,下表越界或者是負值的情況下,得到的結(jié)果是undefined,而不是報錯。
下面我們希望數(shù)組可以取負值下表,規(guī)則如下:
-n表示倒數(shù)第n個元素。例如:-1表示倒數(shù)第一個元素。
使用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()可以把傳入的值轉(zhuǎn)成數(shù)值型。非數(shù)值 --> NaN;
如果是proxyArr.push(3),由于此時的prop是"push",所以不會進入if分支。
如果是proxyArr[-1],此時的prop是"-1",所以會進入到if分支:把prop從-1改成 2 ,從而實現(xiàn)了被代理的效果。
此時,完全可以把proxyArr當作一個數(shù)組來使用,sort,push等方法均可以調(diào)用。Array.isArray(proxyArr) === true
當然,你也可以進一步封裝成工廠函數(shù)。
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);
說明:
reduce
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/98000.html
摘要:前端進階進階構(gòu)建項目一配置最佳實踐狀態(tài)管理之痛點分析與改良開發(fā)中所謂狀態(tài)淺析從時間旅行的烏托邦,看狀態(tài)管理的設(shè)計誤區(qū)使用更好地處理數(shù)據(jù)愛彼迎房源詳情頁中的性能優(yōu)化從零開始,在中構(gòu)建時間旅行式調(diào)試用輕松管理復(fù)雜狀態(tài)如何把業(yè)務(wù)邏輯這個故事講好和 前端進階 webpack webpack進階構(gòu)建項目(一) Webpack 4 配置最佳實踐 react Redux狀態(tài)管理之痛點、分析與...
摘要:存取描述符同時具有以下可選鍵值一個給屬性提供的方法,如果沒有則為。該方法返回值被用作屬性值。值得注意的是屬性描述符必須是數(shù)據(jù)描述符或者存取描述符兩種形式之一,不能同時是兩者??梢院雎苑椒ǖ姆祷刂?。 前言 我們或多或少都聽過數(shù)據(jù)綁定這個詞,數(shù)據(jù)綁定的關(guān)鍵在于監(jiān)聽數(shù)據(jù)的變化,可是對于這樣一個對象:var obj = {value: 1},我們該怎么知道 obj 發(fā)生了改變呢? define...
摘要:查找并返回對象的屬性例例屬性部署了讀取函數(shù)返回的是的參數(shù)對象注意如果的第一個參數(shù)不是對象,則會報錯。它返回一個布爾值,表示是否操作成功用于返回對象的所有屬性使用和實現(xiàn)觀察者模式請參考觀察者模式 1、什么是Reflect?為操作對象而提供的新API 2、為什么要設(shè)計Reflect?(1)將Object對象的屬于語言內(nèi)部的方法放到Reflect對象上,即從Reflect對象上拿Object...
摘要:的出現(xiàn),使用內(nèi)建對象的繼承得以實現(xiàn)。屬性不存在拋出異常是取值操作,而就是賦值操作,可以對屬性值進行驗證。屬性必須為數(shù)字拋出異常接受兩個參數(shù)被讀取屬性的原對象,即代理的目標。這個可以攔截內(nèi)部方法,通過返回數(shù)組的值可以覆寫其行為。 Proxy & Reflect extends的出現(xiàn),使用內(nèi)建對象的繼承得以實現(xiàn)。Proxy可以攔截JS引擎內(nèi)部目標的底層對象操作,這些底層操作被攔截后會觸發(fā)響...
閱讀 485·2019-08-29 12:44
閱讀 3066·2019-08-26 17:49
閱讀 2549·2019-08-26 13:40
閱讀 1227·2019-08-26 13:39
閱讀 3711·2019-08-26 11:59
閱讀 1878·2019-08-26 10:59
閱讀 2547·2019-08-23 18:33
閱讀 2751·2019-08-23 18:30