ES6 Reflect

一赋续、概述

  • Reflect對象與Proxy對象一樣票彪,也是 ES6 為了操作對象而提供的新 API乔妈。Reflect對象的設(shè)計目的有這樣幾個。

  • Reflect 可以用于獲取目標(biāo)對象的行為酸员,它與 Object 類似,但是更易讀讳嘱,為操作對象提供了一種更優(yōu)雅的方式幔嗦。它的方法與 Proxy 是對應(yīng)的。

(1) Object對象的一些明顯屬于語言內(nèi)部的方法(比如Object.defineProperty)沥潭,放到Reflect對象上邀泉。現(xiàn)階段,某些方法同時在ObjectReflect對象上部署钝鸽,未來的新方法將只部署在Reflect對象上汇恤。也就是說,從Reflect對象上可以拿到語言內(nèi)部的方法拔恰。

(2) 修改某些Object方法的返回結(jié)果因谎,讓其變得更合理。比如颜懊,Object.defineProperty(obj, name, desc)在無法定義屬性時财岔,會拋出一個錯誤,而Reflect.defineProperty(obj, name, desc)則會返回false河爹。

// 老寫法
try {
  Object.defineProperty(target, property, attributes);
  // success
} catch (e) {
  // failure
}

// 新寫法
if (Reflect.defineProperty(target, property, attributes)) {
  // success
} else {
  // failure
}

(3) Object操作都變成函數(shù)行為使鹅。某些Object操作是命令式,比如name in objdelete obj[name]昌抠,而Reflect.has(obj, name)Reflect.deleteProperty(obj, name)讓它們變成了函數(shù)行為患朱。

// 老寫法
'assign' in Object // true

// 新寫法
Reflect.has(Object, 'assign') // true

(4)Reflect對象的方法與Proxy對象的方法一一對應(yīng),只要是Proxy對象的方法炊苫,就能在Reflect對象上找到對應(yīng)的方法裁厅。這就讓Proxy對象可以方便地調(diào)用對應(yīng)的Reflect方法,完成默認行為侨艾,作為修改行為的基礎(chǔ)执虹。也就是說,不管Proxy怎么修改默認行為唠梨,你總可以在Reflect上獲取默認行為袋励。

例子1:

Proxy(target, {
  set: function(target, name, value, receiver) {
    var success = Reflect.set(target, name, value, receiver);
    if (success) {
      console.log('property ' + name + ' on ' + target + ' set to ' + value);
    }
    return success;
  }
});

上面代碼中,Proxy方法攔截target對象的屬性賦值行為。它采用Reflect.set方法將值賦值給對象的屬性茬故,確保完成原有的行為盖灸,然后再部署額外的功能。

例子2:

var loggedObj = new Proxy(obj, {
  get(target, name) {
    console.log('get', target, name);
    return Reflect.get(target, name);
  },
  deleteProperty(target, name) {
    console.log('delete' + name);
    return Reflect.deleteProperty(target, name);
  },
  has(target, name) {
    console.log('has' + name);
    return Reflect.has(target, name);
  }
});

上面代碼中磺芭,每一個Proxy對象的攔截操作(get赁炎、deletehas)钾腺,內(nèi)部都調(diào)用對應(yīng)的Reflect方法徙垫,保證原生行為能夠正常執(zhí)行。添加的工作放棒,就是將每一個操作輸出一行日志姻报。

  • 有了Reflect對象以后,很多操作會更易讀间螟。
// 老寫法
Function.prototype.apply.call(Math.floor, undefined, [1.75]) // 1

// 新寫法
Reflect.apply(Math.floor, undefined, [1.75]) // 1

二逗抑、靜態(tài)方法

  • 這些方法的作用,大部分與Object對象的同名方法的作用都是相同的寒亥,而且它與Proxy對象的方法是一一對應(yīng)的邮府。

Reflect對象一共有 13 個靜態(tài)方法。

  1. Reflect.get(target, name, receiver):查找并返回target對象的name屬性溉奕,如果沒有該屬性褂傀,則返回undefined。
  2. Reflect.set(target, name, value, receiver):設(shè)置target對象的name屬性等于value加勤。
  3. Reflect.has(target, name):對應(yīng)name in obj里面的in運算符仙辟。
  4. Reflect.deleteProperty(target, name):等同于delete obj[name],用于刪除對象的屬性鳄梅。
  5. Reflect.ownKeys(target):用于返回對象的所有屬性叠国,基本等同于Object.getOwnPropertyNames與Object.getOwnPropertySymbols之和。
  6. Reflect.getOwnPropertyDescriptor(target,name):基本等同于Object.getOwnPropertyDescriptor戴尸,用于得到指定屬性的描述對象粟焊,將來會替代掉后者。
  7. Reflect.defineProperty(target, name,desc):基本等同于Object.defineProperty孙蒙,用來為對象定義屬性项棠。未來,后者會被逐漸廢除挎峦,請從現(xiàn)在開始就使用Reflect.defineProperty代替它香追。
  8. Reflect.preventExtensions(target):對應(yīng)Object.preventExtensions方法,用于讓一個對象變?yōu)椴豢蓴U展坦胶。它返回一個布爾值透典,表示是否操作成功晴楔。
  9. Reflect.getPrototypeOf(target):用于讀取對象的proto屬性,對應(yīng)Object.getPrototypeOf(obj)峭咒。
  10. Reflect.isExtensible(target):對應(yīng)Object.isExtensible税弃,返回一個布爾值,表示當(dāng)前對象是否可擴展讹语。
  11. Reflect.setPrototypeOf(target,prototype):用于設(shè)置目標(biāo)對象的原型(prototype)钙皮,對應(yīng)Object.setPrototypeOf(obj, newProto)方法蜂科。它返回一個布爾值顽决,表示是否設(shè)置成功。
  12. Reflect.apply(target, thisArg, args):等同于Function.prototype.apply.call(func, thisArg, args)导匣,用于綁定this對象后執(zhí)行給定函數(shù)才菠。
  13. Reflect.construct(target, args):等同于newtarget(…args),這提供了一種不使用new贡定,來調(diào)用構(gòu)造函數(shù)的方法赋访。

三、實例:使用 Proxy 實現(xiàn)觀察者模式

觀察者模式(Observer mode)指的是函數(shù)自動觀察數(shù)據(jù)對象缓待,一旦對象有變化蚓耽,函數(shù)就會自動執(zhí)行。

const person = observable({   //數(shù)據(jù)對象person
  name: '張三',
  age: 20
});

function print() {    //觀察者print
  console.log(`${person.name}, ${person.age}`)
}

observe(print);
person.name = '李四';
// 輸出
// 李四, 20

上面代碼中旋炒,數(shù)據(jù)對象person是觀察目標(biāo)步悠,函數(shù)print是觀察者。一旦數(shù)據(jù)對象發(fā)生變化瘫镇,print就會自動執(zhí)行鼎兽。

觀察者模式實現(xiàn):

使用 Proxy 寫一個觀察者模式的最簡單實現(xiàn),即實現(xiàn)observableobserve這兩個函數(shù)铣除。

思路是observable函數(shù)返回一個原始對象的 Proxy 代理谚咬,攔截賦值操作,觸發(fā)充當(dāng)觀察者的各個函數(shù)尚粘。

const queuedObservers = new Set();  //先定義了一個Set集合

const observe = fn => queuedObservers.add(fn);  
const observable = obj => new Proxy(obj, {set});  //observable函數(shù)返回原始對象的代理

function set(target, key, value, receiver) {
  const result = Reflect.set(target, key, value, receiver);
  queuedObservers.forEach(observer => observer());
  return result;
}

上面代碼中择卦,

  1. 先定義了一個Set集合,所有觀察者函數(shù)都放進這個集合郎嫁。
  2. 然后互捌,observable函數(shù)返回原始對象的代理,攔截賦值操作行剂。
  3. 攔截函數(shù)set之中秕噪,會自動執(zhí)行所有觀察者。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末厚宰,一起剝皮案震驚了整個濱河市腌巾,隨后出現(xiàn)的幾起案子遂填,更是在濱河造成了極大的恐慌,老刑警劉巖澈蝙,帶你破解...
    沈念sama閱讀 212,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吓坚,死亡現(xiàn)場離奇詭異,居然都是意外死亡灯荧,警方通過查閱死者的電腦和手機礁击,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來逗载,“玉大人哆窿,你說我怎么就攤上這事±髡澹” “怎么了挚躯?”我有些...
    開封第一講書人閱讀 158,369評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長擦秽。 經(jīng)常有香客問我码荔,道長,這世上最難降的妖魔是什么感挥? 我笑而不...
    開封第一講書人閱讀 56,799評論 1 285
  • 正文 為了忘掉前任缩搅,我火速辦了婚禮,結(jié)果婚禮上触幼,老公的妹妹穿的比我還像新娘硼瓣。我一直安慰自己,他們只是感情好域蜗,可當(dāng)我...
    茶點故事閱讀 65,910評論 6 386
  • 文/花漫 我一把揭開白布巨双。 她就那樣靜靜地躺著,像睡著了一般霉祸。 火紅的嫁衣襯著肌膚如雪筑累。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,096評論 1 291
  • 那天丝蹭,我揣著相機與錄音慢宗,去河邊找鬼。 笑死奔穿,一個胖子當(dāng)著我的面吹牛镜沽,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播贱田,決...
    沈念sama閱讀 39,159評論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼缅茉,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了男摧?” 一聲冷哼從身側(cè)響起蔬墩,我...
    開封第一講書人閱讀 37,917評論 0 268
  • 序言:老撾萬榮一對情侶失蹤译打,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后拇颅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體奏司,經(jīng)...
    沈念sama閱讀 44,360評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,673評論 2 327
  • 正文 我和宋清朗相戀三年樟插,在試婚紗的時候發(fā)現(xiàn)自己被綠了韵洋。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,814評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡黄锤,死狀恐怖搪缨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情猜扮,我是刑警寧澤勉吻,帶...
    沈念sama閱讀 34,509評論 4 334
  • 正文 年R本政府宣布监婶,位于F島的核電站旅赢,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏惑惶。R本人自食惡果不足惜煮盼,卻給世界環(huán)境...
    茶點故事閱讀 40,156評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望带污。 院中可真熱鬧僵控,春花似錦、人聲如沸鱼冀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽千绪。三九已至充易,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間荸型,已是汗流浹背盹靴。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留瑞妇,地道東北人稿静。 一個月前我還...
    沈念sama閱讀 46,641評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像辕狰,于是被迫代替她去往敵國和親改备。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,728評論 2 351

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

  • 本人自學(xué)es6已經(jīng)有一段時間了蔓倍,只覺得有些時候很是枯燥無味悬钳, 時而又覺得在以后的職業(yè)生涯中會很有用润脸,因為es6的很...
    可樂_37d3閱讀 1,521評論 0 0
  • 概述 Reflect 對象是一個全局的普通的對象。Reflect 的原型就是 Object他去。我們來驗證下 Refl...
    前端_Fn閱讀 483評論 0 0
  • 1.概述 Reflect對象和Proxy對象一樣毙驯,也是ES6為了操作對象而提供新的API,Reflect對象的設(shè)計...
    前端mamba24閱讀 174評論 0 0
  • Reflect對象與Proxy對象一樣灾测,也是 ES6 為了操作對象而提供的新 API爆价。Reflect對象的設(shè)計目的...
    SunshineBrother閱讀 405評論 0 2
  • Reflect對象與Proxy對象一樣,也是 ES6 為了操作對象而提供的新 API Reflect對象的設(shè)計目的...
    coderfl閱讀 180評論 0 0