日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

“睡服”面试官系列第十七篇之Reflect(建议收藏学习)

發(fā)布時(shí)間:2023/12/10 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 “睡服”面试官系列第十七篇之Reflect(建议收藏学习) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

目錄

?

1. 概述

2. 靜態(tài)方法

2.1Reflect.get(target, name, receiver)

2.2Reflect.set(target, name, value, receiver)

2.3Reflect.has(obj, name)

2.4Reflect.deleteProperty(obj, name)

2.5Reflect.construct(target, args)

2.6Reflect.getPrototypeOf(obj)

2.7Reflect.setPrototypeOf(obj, newProto)

2.8Reflect.apply(func, thisArg, args)

2.9Reflect.defineProperty(target, propertyKey, attributes)

2.10Reflect.getOwnPropertyDescriptor(target, propertyKey)

2.11Reflect.isExtensible (target)

?2.12Reflect.preventExtensions(target)

2.13Reflect.ownKeys (target)

3. 實(shí)例:使用 Proxy 實(shí)現(xiàn)觀察者模式


1. 概述

Reflect 對(duì)象與 Proxy 對(duì)象一樣,也是 ES6 為了操作對(duì)象而提供的新 API。 Reflect 對(duì)象的設(shè)計(jì)目的有這樣幾個(gè)。
(1) 將 Object 對(duì)象的一些明顯屬于語(yǔ)言內(nèi)部的方法(比如 Object.defineProperty ),放到 Reflect 對(duì)象上。現(xiàn)階段,某些方法同時(shí)在 Object 和
Reflect 對(duì)象上部署,未來(lái)的新方法將只部署在 Reflect 對(duì)象上。也就是說(shuō),從 Reflect 對(duì)象上可以拿到語(yǔ)言內(nèi)部的方法。
(2) 修改某些 Object 方法的返回結(jié)果,讓其變得更合理。比如, Object.defineProperty(obj, name, desc) 在無(wú)法定義屬性時(shí),會(huì)拋出一個(gè)錯(cuò)誤,而
Reflect.defineProperty(obj, name, desc) 則會(huì)返回 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 obj 和 delete obj[name] ,而 Reflect.has(obj, name) 和
Reflect.deleteProperty(obj, name) 讓它們變成了函數(shù)行為

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

(4) Reflect 對(duì)象的方法與 Proxy 對(duì)象的方法一一對(duì)應(yīng),只要是 Proxy 對(duì)象的方法,就能在 Reflect 對(duì)象上找到對(duì)應(yīng)的方法。這就讓 Proxy 對(duì)象可以方便
地調(diào)用對(duì)應(yīng)的 Reflect 方法,完成默認(rèn)行為,作為修改行為的基礎(chǔ)。也就是說(shuō),不管 Proxy 怎么修改默認(rèn)行為,你總可以在 Reflect 上獲取默認(rèn)行為

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

上面代碼中, Proxy 方法攔截 target 對(duì)象的屬性賦值行為。它采用 Reflect.set 方法將值賦值給對(duì)象的屬性,確保完成原有的行為,然后再部署額外的功
能。
下面是另一個(gè)例子

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); } });

上面代碼中,每一個(gè) Proxy 對(duì)象的攔截操作( get 、 delete 、 has ),內(nèi)部都調(diào)用對(duì)應(yīng)的 Reflect 方法,保證原生行為能夠正常執(zhí)行。添加的工作,就是
將每一個(gè)操作輸出一行日志。
有了 Reflect 對(duì)象以后,很多操作會(huì)更易讀。

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

2. 靜態(tài)方法

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

Reflect.apply(target, thisArg, args) Reflect.construct(target, args) Reflect.get(target, name, receiver) Reflect.set(target, name, value, receiver) Reflect.defineProperty(target, name, desc) Reflect.deleteProperty(target, name) Reflect.has(target, name) Reflect.ownKeys(target) Reflect.isExtensible(target) Reflect.preventExtensions(target) Reflect.getOwnPropertyDescriptor(target, name) Reflect.getPrototypeOf(target) Reflect.setPrototypeOf(target, prototype)

上面這些方法的作用,大部分與 Object 對(duì)象的同名方法的作用都是相同的,而且它與 Proxy 對(duì)象的方法是一一對(duì)應(yīng)的。下面是對(duì)它們的解釋。

2.1Reflect.get(target, name, receiver)

Reflect.get 方法查找并返回 target 對(duì)象的 name 屬性,如果沒(méi)有該屬性,則返回 undefined 。

var myObject = { foo: 1, bar: 2, get baz() { return this.foo + this.bar; }, } Reflect.get(myObject, 'foo') // 1 Reflect.get(myObject, 'bar') // 2 Reflect.get(myObject, 'baz') // 3

如果 name 屬性部署了讀取函數(shù)(getter),則讀取函數(shù)的 this 綁定 receiver 。

var myObject = { foo: 1, bar: 2, get baz() { return this.foo + this.bar; }, }; var myReceiverObject = { foo: 4, bar: 4, }; Reflect.get(myObject, 'baz', myReceiverObject) // 8

如果第一個(gè)參數(shù)不是對(duì)象, Reflect.get 方法會(huì)報(bào)錯(cuò)。

Reflect.get(1, 'foo') // 報(bào)錯(cuò) Reflect.get(false, 'foo') // 報(bào)錯(cuò)

2.2Reflect.set(target, name, value, receiver)

Reflect.set 方法設(shè)置 target 對(duì)象的 name 屬性等于 value

var myObject = { foo: 1, set bar(value) { return this.foo = value; }, } myObject.foo // 1 Reflect.set(myObject, 'foo', 2); myObject.foo // 2 Reflect.set(myObject, 'bar', 3) myObject.foo // 3

如果 name 屬性設(shè)置了賦值函數(shù),則賦值函數(shù)的 this 綁定 receiver 。

var myObject = { foo: 4, set bar(value) { return this.foo = value; }, }; var myReceiverObject = { foo: 0, }; Reflect.set(myObject, 'bar', 1, myReceiverObject); myObject.foo // 4 myReceiverObject.foo // 1

注意,如果 Proxy 對(duì)象和 Reflect 對(duì)象聯(lián)合使用,前者攔截賦值操作,后者完成賦值的默認(rèn)行為,而且傳入了 receiver ,那么 Reflect.set 會(huì)觸發(fā)
Proxy.defineProperty 攔截。

let p = { a: 'a' }; let handler = { set(target, key, value, receiver) { console.log('set'); Reflect.set(target, key, value, receiver) }, defineProperty(target, key, attribute) { console.log('defineProperty'); Reflect.defineProperty(target, key, attribute); } }; let obj = new Proxy(p, handler); obj.a = 'A'; // set // defineProperty

上面代碼中, Proxy.set 攔截里面使用了 Reflect.set ,而且傳入了 receiver ,導(dǎo)致觸發(fā) Proxy.defineProperty 攔截。這是因?yàn)?Proxy.set 的
receiver 參數(shù)總是指向當(dāng)前的 Proxy 實(shí)例(即上例的 obj ),而 Reflect.set 一旦傳入 receiver ,就會(huì)將屬性賦值到 receiver 上面(即 obj ),導(dǎo)致
觸發(fā) defineProperty 攔截。如果 Reflect.set 沒(méi)有傳入 receiver ,那么就不會(huì)觸發(fā) defineProperty 攔截。

let p = { a: 'a' }; let handler = { set(target, key, value, receiver) { console.log('set'); Reflect.set(target, key, value) }, defineProperty(target, key, attribute) { console.log('defineProperty'); Reflect.defineProperty(target, key, attribute); } }; let obj = new Proxy(p, handler); obj.a = 'A'; // set

如果第一個(gè)參數(shù)不是對(duì)象, Reflect.set 會(huì)報(bào)錯(cuò)

Reflect.set(1, 'foo', {}) // 報(bào)錯(cuò) Reflect.set(false, 'foo', {}) // 報(bào)錯(cuò)

2.3Reflect.has(obj, name)

Reflect.has 方法對(duì)應(yīng) name in obj 里面的 in 運(yùn)算符。

var myObject = { foo: 1, }; // 舊寫法 'foo' in myObject // true 上一章 下一章 2017/11/20 Reflect - ECMAScript 6入門 http://es6.ruanyifeng.com/#docs/reflect 5/9 // 新寫法 Reflect.has(myObject, 'foo') // true

如果第一個(gè)參數(shù)不是對(duì)象, Reflect.has 和 in 運(yùn)算符都會(huì)報(bào)錯(cuò)

2.4Reflect.deleteProperty(obj, name)

Reflect.deleteProperty 方法等同于 delete obj[name] ,用于刪除對(duì)象的屬性。
?

const myObj = { foo: 'bar' }; // 舊寫法 delete myObj.foo; // 新寫法 Reflect.deleteProperty(myObj, 'foo');

該方法返回一個(gè)布爾值。如果刪除成功,或者被刪除的屬性不存在,返回 true ;刪除失敗,被刪除的屬性依然存在,返回 false 。

2.5Reflect.construct(target, args)

Reflect.construct 方法等同于 new target(...args) ,這提供了一種不使用 new ,來(lái)調(diào)用構(gòu)造函數(shù)的方法

function Greeting(name) { this.name = name; } // new 的寫法 const instance = new Greeting('張三'); // Reflect.construct 的寫法 const instance = Reflect.construct(Greeting, ['張三']);

2.6Reflect.getPrototypeOf(obj)

Reflect.getPrototypeOf 方法用于讀取對(duì)象的 __proto__ 屬性,對(duì)應(yīng) Object.getPrototypeOf(obj) 。

const myObj = new FancyThing(); // 舊寫法 Object.getPrototypeOf(myObj) === FancyThing.prototype; // 新寫法 Reflect.getPrototypeOf(myObj) === FancyThing.prototype;

Reflect.getPrototypeOf 和 Object.getPrototypeOf 的一個(gè)區(qū)別是,如果參數(shù)不是對(duì)象, Object.getPrototypeOf 會(huì)將這個(gè)參數(shù)轉(zhuǎn)為對(duì)象,然后再運(yùn)
行,而 Reflect.getPrototypeOf 會(huì)報(bào)錯(cuò)。

Object.getPrototypeOf(1) // Number {[[PrimitiveValue]]: 0} Reflect.getPrototypeOf(1) // 報(bào)錯(cuò)

2.7Reflect.setPrototypeOf(obj, newProto)

Reflect.setPrototypeOf 方法用于設(shè)置對(duì)象的 __proto__ 屬性,返回第一個(gè)參數(shù)對(duì)象,對(duì)應(yīng) Object.setPrototypeOf(obj, newProto)

const myObj = new FancyThing(); // 舊寫法 Object.setPrototypeOf(myObj, OtherThing.prototype); // 新寫法 Reflect.setPrototypeOf(myObj, OtherThing.prototype);

如果第一個(gè)參數(shù)不是對(duì)象, Object.setPrototypeOf 會(huì)返回第一個(gè)參數(shù)本身,而 Reflect.setPrototypeOf 會(huì)報(bào)錯(cuò)。

Object.setPrototypeOf(1, {}) // 1 Reflect.setPrototypeOf(1, {}) // TypeError: Reflect.setPrototypeOf called on non-object

如果第一個(gè)參數(shù)是 undefined 或 null , Object.setPrototypeOf 和 Reflect.setPrototypeOf 都會(huì)報(bào)錯(cuò)。

Object.setPrototypeOf(null, {}) // TypeError: Object.setPrototypeOf called on null or undefined Reflect.setPrototypeOf(null, {}) // TypeError: Reflect.setPrototypeOf called on non-object

2.8Reflect.apply(func, thisArg, args)

Reflect.apply 方法等同于 Function.prototype.apply.call(func, thisArg, args) ,用于綁定 this 對(duì)象后執(zhí)行給定函數(shù)。
一般來(lái)說(shuō),如果要綁定一個(gè)函數(shù)的 this 對(duì)象,可以這樣寫 fn.apply(obj, args) ,但是如果函數(shù)定義了自己的 apply 方法,就只能寫成
Function.prototype.apply.call(fn, obj, args) ,采用 Reflect 對(duì)象可以簡(jiǎn)化這種操作。

const ages = [11, 33, 12, 54, 18, 96]; // 舊寫法 const youngest = Math.min.apply(Math, ages); const oldest = Math.max.apply(Math, ages); const type = Object.prototype.toString.call(youngest); // 新寫法 const youngest = Reflect.apply(Math.min, Math, ages); const oldest = Reflect.apply(Math.max, Math, ages); const type = Reflect.apply(Object.prototype.toString, youngest, []);

2.9Reflect.defineProperty(target, propertyKey, attributes)

Reflect.defineProperty 方法基本等同于 Object.defineProperty ,用來(lái)為對(duì)象定義屬性。未來(lái),后者會(huì)被逐漸廢除,請(qǐng)從現(xiàn)在開(kāi)始就使用
Reflect.defineProperty 代替它

function MyDate() { /*…*/ } // 舊寫法 Object.defineProperty(MyDate, 'now', { value: () => Date.now() }); // 新寫法 Reflect.defineProperty(MyDate, 'now', { value: () => Date.now() })

如果 Reflect.defineProperty 的第一個(gè)參數(shù)不是對(duì)象,就會(huì)拋出錯(cuò)誤,比如 Reflect.defineProperty(1, 'foo') 。

2.10Reflect.getOwnPropertyDescriptor(target, propertyKey)

Reflect.getOwnPropertyDescriptor 基本等同于 Object.getOwnPropertyDescriptor ,用于得到指定屬性的描述對(duì)象,將來(lái)會(huì)替代掉后者

var myObject = {}; Object.defineProperty(myObject, 'hidden', { value: true, enumerable: false, }); // 舊寫法 var theDescriptor = Object.getOwnPropertyDescriptor(myObject, 'hidden'); // 新寫法 var theDescriptor = Reflect.getOwnPropertyDescriptor(myObject, 'hidden')

Reflect.getOwnPropertyDescriptor 和 Object.getOwnPropertyDescriptor 的一個(gè)區(qū)別是,如果第一個(gè)參數(shù)不是對(duì)象,
Object.getOwnPropertyDescriptor(1, 'foo') 不報(bào)錯(cuò),返回 undefined ,而 Reflect.getOwnPropertyDescriptor(1, 'foo') 會(huì)拋出錯(cuò)誤,表示參數(shù)非

2.11Reflect.isExtensible (target)

Reflect.isExtensible 方法對(duì)應(yīng) Object.isExtensible ,返回一個(gè)布爾值,表示當(dāng)前對(duì)象是否可擴(kuò)展。

const myObject = {}; // 舊寫法 Object.isExtensible(myObject) // true // 新寫法 Reflect.isExtensible(myObject) // true

如果參數(shù)不是對(duì)象, Object.isExtensible 會(huì)返回 false ,因?yàn)榉菍?duì)象本來(lái)就是不可擴(kuò)展的,而 Reflect.isExtensible 會(huì)報(bào)錯(cuò)

Object.isExtensible(1) // false Reflect.isExtensible(1) // 報(bào)錯(cuò)

?2.12Reflect.preventExtensions(target)

Reflect.preventExtensions 對(duì)應(yīng) Object.preventExtensions 方法,用于讓一個(gè)對(duì)象變?yōu)椴豢蓴U(kuò)展。它返回一個(gè)布爾值,表示是否操作成功

var myObject = {}; // 舊寫法 Object.preventExtensions(myObject) // Object {} // 新寫法 Reflect.preventExtensions(myObject) // true

如果參數(shù)不是對(duì)象, Object.preventExtensions 在 ES5 環(huán)境報(bào)錯(cuò),在 ES6 環(huán)境返回傳入的參數(shù),而 Reflect.preventExtensions 會(huì)報(bào)錯(cuò)。

// ES5 環(huán)境 Object.preventExtensions(1) // 報(bào)錯(cuò) // ES6 環(huán)境 Object.preventExtensions(1) // 1 // 新寫法 Reflect.preventExtensions(1) // 報(bào)錯(cuò)

2.13Reflect.ownKeys (target)

Reflect.ownKeys 方法用于返回對(duì)象的所有屬性,基本等同于 Object.getOwnPropertyNames 與 Object.getOwnPropertySymbols 之和

var myObject = { foo: 1, bar: 2, [Symbol.for('baz')]: 3, [Symbol.for('bing')]: 4, }; // 舊寫法 Object.getOwnPropertyNames(myObject) // ['foo', 'bar'] Object.getOwnPropertySymbols(myObject) //[Symbol(baz), Symbol(bing)] // 新寫法 Reflect.ownKeys(myObject) // ['foo', 'bar', Symbol(baz), Symbol(bing)]

3. 實(shí)例:使用 Proxy 實(shí)現(xiàn)觀察者模式

觀察者模式(Observer mode)指的是函數(shù)自動(dòng)觀察數(shù)據(jù)對(duì)象,一旦對(duì)象有變化,函數(shù)就會(huì)自動(dòng)執(zhí)行。

const person = observable({ name: '張三', age: 20 }); function print() { console.log(`${person.name}, ${person.age}`) } observe(print); person.name = '李四'; // 輸出 // 李四, 20

上面代碼中,數(shù)據(jù)對(duì)象 person 是觀察目標(biāo),函數(shù) print 是觀察者。一旦數(shù)據(jù)對(duì)象發(fā)生變化, print 就會(huì)自動(dòng)執(zhí)行。
下面,使用 Proxy 寫一個(gè)觀察者模式的最簡(jiǎn)單實(shí)現(xiàn),即實(shí)現(xiàn) observable 和 observe 這兩個(gè)函數(shù)。思路是 observable 函數(shù)返回一個(gè)原始對(duì)象的 Proxy 代
理,攔截賦值操作,觸發(fā)充當(dāng)觀察者的各個(gè)函數(shù)。

const queuedObservers = new Set(); const observe = fn => queuedObservers.add(fn); const observable = obj => new Proxy(obj, {set}); function set(target, key, value, receiver) { const result = Reflect.set(target, key, value, receiver); queuedObservers.forEach(observer => observer()); return result; }

上面代碼中,先定義了一個(gè) Set 集合,所有觀察者函數(shù)都放進(jìn)這個(gè)集合。然后, observable 函數(shù)返回原始對(duì)象的代理,攔截賦值操作。攔截函數(shù) set 之
中,會(huì)自動(dòng)執(zhí)行所有觀察者

總結(jié)

本博客源于本人閱讀相關(guān)書籍和視頻總結(jié),創(chuàng)作不易,謝謝點(diǎn)贊支持。學(xué)到就是賺到。我是歌謠,勵(lì)志成為一名優(yōu)秀的技術(shù)革新人員。

歡迎私信交流,一起學(xué)習(xí),一起成長(zhǎng)。

推薦鏈接 其他文件目錄參照

“睡服“面試官系列之各系列目錄匯總(建議學(xué)習(xí)收藏)

總結(jié)

以上是生活随笔為你收集整理的“睡服”面试官系列第十七篇之Reflect(建议收藏学习)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 特一级黄色 | 99re免费视频精品全部 | www.4虎 | 韩国黄色av | 国产九色av | 国产免费网址 | 国产午夜精品久久久久 | 香蕉久久夜色精品国产使用方法 | 两性视频久久 | 婷婷亚洲一区 | 黄a毛片| 天天干b | 殴美黄色大片 | 综合色天天| 韩国美女av | 亚洲a一区| 亚洲欧美日韩综合在线 | 亚洲一区二区高清视频 | 久久999 | 亚洲中文字幕无码专区 | 德国性经典xxxx性hd | 熟女肥臀白浆大屁股一区二区 | 超碰在线人人干 | 亚洲精品乱码久久久久久蜜桃欧美 | 国产乱子伦精品无码专区 | 美女被草网站 | 秋霞欧美在线观看 | 国产女主播自拍 | 蜜桃av噜噜一区二区三区麻豆 | 国产精品三级 | 少妇一级淫免费放 | 婷婷在线观看视频 | 国产精品视频久久久久 | 国产寡妇色xxⅹ交肉视频 | 日韩图片一区 | 亚洲日本精品一区 | 日本草草影院 | 女儿的朋友在线播放 | 一卡二卡在线 | 成人免费大片黄在线播放 | 国产成年无码久久久久毛片 | 免费特级毛片 | 亚洲国产av一区二区三区 | 欧美成年人 | 日本黄大片在线观看 | 久久综合精品国产二区无码不卡 | 欧美精品黄 | 夜夜夜爽 | 午夜精品福利一区二区蜜股av | 日韩欧美亚洲国产精品字幕久久久 | 精品一区二区日韩 | 欧美无玛| 在线免费观看一级片 | 日本不卡视频 | 亚洲第一成肉网 | 欧洲黄色网| www.亚洲在线 | 青青草国内自拍 | 老外黄色一级片 | 91精品国自产在线观看 | 色综合自拍 | 国产一区日韩精品 | 日本wwww视频 | 男人天堂2020 | 男人添女人下部高潮全视频 | 嫩草在线观看视频 | 国产亚洲片 | 午夜国产一级 | 一区二区三区四区五区六区 | 亚洲网视频 | 超碰91在线 | 欧美不卡高清 | 91香草视频 | 福利在线一区 | 欧美日韩成人一区二区在线观看 | 韩国一区二区在线播放 | 国产一级高清 | 午夜久久久久久久久久久 | 色综合成人 | 欧美性受xxxx黑人 | 91成人免费在线观看视频 | 打白嫩屁屁网站视频短裙 | 日韩中文字幕在线看 | 综合网伊人 | 中文字幕av一区二区三区人妻少妇 | 麻豆网站免费观看 | 四川操bbb | 成人激情综合网 | 国产免费又粗又猛又爽 | 久久久久麻豆v国产精华液好用吗 | 久久久久香蕉视频 | 国产一级做a | 午夜伦理福利视频 | 欧美精品乱码久久久久久 | 色老板最新地址 | 在线观看9.1 | 欧美深性狂猛ⅹxxx深喉 | 日本人xxxⅹ18hd19hd | 女厕厕露p撒尿八个少妇 |