ES6中的Proxy<代理>和Reflect<反射>

先看個(gè)題目

讓下列表達(dá)式成立

a === 1 && a === 2 && a === 3

我大致的思路是定義變量a = 0 每次取a得值時(shí)瓮具,先 a++蜈项,再返回。
ok要在完成取值之前攔截一步皿桑,并且輸出我們想要的值,就需要用的es5中的數(shù)據(jù)劫持了蔬啡。
于是我咔咔寫(xiě)出了下面的代碼:

window['a'] = 0;
    Object.defineProperty(window,'a',{
        get() {
            window['a']++
            return window['a']
        }
    })

然后就咔咔的報(bào)錯(cuò)了诲侮,報(bào)錯(cuò)原因是堆棧溢出。

我思考了一下箱蟆,原來(lái)如此沟绪,當(dāng)我取a的值時(shí),get劫持了我的操作空猜,此時(shí)我使a++,相當(dāng)于又取了a的值绽慈,又重復(fù)劫持了一次,所以死循環(huán)了辈毯。

所以我想我換一個(gè)不被劫持的值不得了坝疼,于是我咔咔寫(xiě)下了下面的代碼:

let count = 0;
Object.defineProperty(window,'a',{
    get() {
        count++;
        return count;
    }
})

結(jié)果果然沒(méi)錯(cuò)。

上面兩端代碼中谆沃,都用到了Object.defineProperty裙士。

官方解釋?zhuān)篛bject.defineProperty() 方法會(huì)直接在一個(gè)對(duì)象上定義一個(gè)新屬性,或者修改一個(gè)對(duì)象的現(xiàn)有屬性管毙, 并返回這個(gè)對(duì)象。

它可以定義一個(gè)新屬性桌硫,比如我上面的a夭咬,本來(lái)是不存在,卻被程序定義出來(lái)了铆隘。
或者修改一個(gè)現(xiàn)有的屬性卓舵,比如第一段程序中的window['a'],本來(lái)就有膀钠。

OK掏湾,據(jù)說(shuō)Vue2.x中的數(shù)據(jù)雙向綁定就用到了這個(gè)玩意。

如果想深入了解數(shù)據(jù)雙向綁定的實(shí)現(xiàn)肿嘲,請(qǐng)看文章:http://www.cnblogs.com/libin-1/p/6893712.html

接著說(shuō)Proxy

Proxy表面上和defineProperty差不多融击,后者能實(shí)現(xiàn)的,前者也能實(shí)現(xiàn)雳窟,比如監(jiān)聽(tīng)對(duì)象內(nèi)一個(gè)屬性的變化

let obj = new Proxy({a:1},{
    get(target, p, receiver) {
        console.log('取值')
    },
    set(target, p, value, receiver) {
        console.log('改值')
    }
})

相比defineProperty尊浪,Proxy具有下面幾個(gè)優(yōu)勢(shì)

  1. 監(jiān)聽(tīng)對(duì)象內(nèi)所有屬性時(shí),不需要遍歷,而defineProperty則需要遍歷拇涤。
  2. 支持?jǐn)?shù)組
  3. 不需要對(duì) keys 進(jìn)行遍歷捣作。這解決Object.defineProperty() 的第二個(gè)問(wèn)題.Proxy 是針對(duì)整個(gè) obj 的。所以 obj 內(nèi)部包含的所有的 key 鹅士,都可以走進(jìn) set券躁。(省了一個(gè) Object.keys() 的遍歷)

關(guān)于Proxy支持的攔截方法可參考官方文檔:
http://es6.ruanyifeng.com/#docs/proxy#Proxy-%E5%AE%9E%E4%BE%8B%E7%9A%84%E6%96%B9%E6%B3%95

Reflect對(duì)象

還是剛才的代碼

let obj = new Proxy({a:1},{
    get(target, p, receiver) {
        console.log('取值')
    }
})
let a = obj.a

我咔咔的就輸出了a,結(jié)果卻是undefined,為啥掉盅,因?yàn)間et方法里只是攔截和監(jiān)聽(tīng)也拜,但是方法卻沒(méi)有返回。

我按照官方教程輸出了返回值怔接,代碼如下:

let obj = new Proxy({a:1},{
    get(target, p, receiver) {
        return Reflect.get(target,p,receiver)
    }
})
let a = obj.a

取到了obj.a的值搪泳。
所以啥是Reflect?
官方解釋?zhuān)簽椴僮鲗?duì)象而提供的新API
http://es6.ruanyifeng.com/#docs/reflect

Reflect的優(yōu)勢(shì)
1.將Object對(duì)象的屬于語(yǔ)言?xún)?nèi)部的方法放到Reflect對(duì)象上,即從Reflect對(duì)象上拿Object對(duì)象內(nèi)部方法扼脐。

let obj = {a:1};

// old
Object.defineProperty();

// new
Reflect.deleteProperty()
  1. 將用 老Object方法 報(bào)錯(cuò)的情況岸军,改為返回false
// old
try {
  Object.defineProperty(target, property, attributes);
  // success
} catch (e) {
  // failure
}
// new
if (Reflect.defineProperty(target, property, attributes)) {
  // success
} else {
  // failure
}
  1. 讓Object操作變成函數(shù)行為
// old
'name' in Object
// new
Reflect.has(Object,'name')
  1. 在Proxy上有的方法,在Reflect就一定有瓦侮。在Proxy修改了默認(rèn)行為后艰赞,可通過(guò)Reflect保證默認(rèn)行為正常運(yùn)行。
let obj = new Proxy({a:1},{
    get(target, p, receiver) {
        // 改變默認(rèn)行文
        console.log('取值')
        
        // 使默認(rèn)行為正常執(zhí)行 
        return Reflect.get(target,p,receiver)
    }
})

let a = obj.a 
console.log(a) // 1

Reflect對(duì)象擁有的方法:
請(qǐng)參考官方文檔:http://es6.ruanyifeng.com/#docs/reflect

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末肚吏,一起剝皮案震驚了整個(gè)濱河市方妖,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌罚攀,老刑警劉巖党觅,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異斋泄,居然都是意外死亡杯瞻,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén)炫掐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)魁莉,“玉大人,你說(shuō)我怎么就攤上這事募胃∑煅洌” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵痹束,是天一觀(guān)的道長(zhǎng)检疫。 經(jīng)常有香客問(wèn)我,道長(zhǎng)参袱,這世上最難降的妖魔是什么电谣? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任秽梅,我火速辦了婚禮,結(jié)果婚禮上剿牺,老公的妹妹穿的比我還像新娘企垦。我一直安慰自己,他們只是感情好晒来,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布钞诡。 她就那樣靜靜地躺著,像睡著了一般湃崩。 火紅的嫁衣襯著肌膚如雪荧降。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,301評(píng)論 1 301
  • 那天攒读,我揣著相機(jī)與錄音朵诫,去河邊找鬼。 笑死薄扁,一個(gè)胖子當(dāng)著我的面吹牛剪返,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播邓梅,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼脱盲,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了日缨?” 一聲冷哼從身側(cè)響起钱反,我...
    開(kāi)封第一講書(shū)人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎匣距,沒(méi)想到半個(gè)月后面哥,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡毅待,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年幢竹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片恩静。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蹲坷,靈堂內(nèi)的尸體忽然破棺而出驶乾,到底是詐尸還是另有隱情,我是刑警寧澤循签,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布级乐,位于F島的核電站,受9級(jí)特大地震影響县匠,放射性物質(zhì)發(fā)生泄漏风科。R本人自食惡果不足惜撒轮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望贼穆。 院中可真熱鬧题山,春花似錦、人聲如沸故痊。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)愕秫。三九已至慨菱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間戴甩,已是汗流浹背符喝。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留甜孤,地道東北人协饲。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像课蔬,于是被迫代替她去往敵國(guó)和親囱稽。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容