【ES6系列】Reflect

概述

Reflect 是爲了操作對象而提供的 API,它的設計目的有以下幾個。

  • Object 上一些屬於語言內部的方法 (比如 Object.defineProperty)放在 Reflect 對象上。現階段,某些方法同時在 ObjectRelfect 對象上部署,未來的新方法將只部署在 Reflect 對象上。
  • 修改某些 Object 方法的返回結果,讓其更加完善。比如,Object.defineProperty(obj,name,desc) 在無法定義屬性時,會拋出一個異常,而 Reflect.defineProperty(obj,name,desc) 則會返回 false
  • Object 操作變成函數行爲。某些 Object 操作是命令式的,比如 name in objdelete obj[name] ,而 Reflect.has(obj,name)Reflect.deleteProperty(obj,name) 讓他們變成了函數行爲。
  • Reflect 對象的方法與 Proxy 對象的方法對應,只要是 Proxy 對象的方法,就能在 Reflect 對象上找到對應的方法。這就讓 Proxy 對象可以方便的調用對應的方法,完成默認行爲。也就是說,不管 Proxy 怎麼修改默認行爲,你總可以在 Reflect 上獲取默認行爲。

靜態方法

Reflect 對象上一共有13個靜態方法,這些大部分與 Object 對象同名甚至作用都是相同的,而且它與 Proxy 對象的方法是對應的。

Reflect.get(target,name,receiver)

Reflect.get() 方法查找並返回 target 對象的 name 屬性,如果沒有該屬性,則返回 undefined。如果 name 屬性部署了 getter ,那麼將 receiver 綁定到函數中的 this

let person = {
    name:"jonas",
    get age(){
        return this.age
    }
}

let jonas = {age:18}

let name = Reflect.get(person,"name")
let age = Reflect.get(person,"age",jonas)
console.log(name) //jonas
console.log(age) //18

另外,如果第一個參數不是對象,而是基本類型數據,則會報錯。

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

設置 target 對象的 name 屬性爲 value ,如果屬性設置了 setter 則將 receiver 綁定到函數中的 this

let person = {
    name:"jonas",
    get age(){
        return this.age
    },
    set age(value){
        return this.age = value
    }
}

let jonas = {age:18}

Reflect.set(person,"age",20,jonas)

console.log(jonas.age) //20

同樣的,如果第一個參數不是對象,則會報錯。

Reflect.has(obj,name)

判斷 name 是否爲 obj 對象中的屬性,相當於 name in obj 。方法返回布爾值。

let person = {name:"jonas"}
let result = Reflect.has(person,"name")
console.log(result) //true

Reflect.deleteProperty(obj,name)

刪除對象中的屬性,相當於 delete obj[name],該方法返回布爾值,如果屬性不存在或刪除成功,則返回 true

let person = {name:"jonas"}
let result = Reflect.deleteProperty(person,"name")
console.log(result) //true
console.log(person) ///{}

Reflect.construct(target,args)

該方法等同於 new 運算符,提供了一種不使用 new 關鍵字實例化的方式。其中 target 是構造函數,args 則是函數的參數列表。

function Person(name,age){
    this.name = name
    this.age = age
}

let person = Reflect.construct(Person,["jonas",18])
console.log(person) //Person { name: 'jonas', age: 18 }

Reflect.getPrototypeOf(obj)

用於讀取對象的 __proto__ 屬性,對應 Object.getPrototypeOf(obj)

Reflect.getPrototypeOf()Object.getPrototypeOf() 的區別是後者如果第一個參數不是對象,則會轉換爲對象,而前者會報錯。

Reflect.setPrototypeOf(obj,proto)

該方法用於設置目標對象的原型,與 Object.setPrototypeOf() 對應,返回值是一個布爾值,表示是否設置成功。

提點:封閉對象,無法擴展對象,凍結對象不能設置原型。

如果第一個參數不是,這兩個方法都會報錯。

Reflect.apply(func,thisArg,args)

該方法等同於 Function.prototype.apply.call() 用於綁定 this 對象後執行函數。

一般情況下,如果需要綁定函數 this,可以直接 fn.call(),但是如果函數重寫了 apply() 方法,就只能通過 Function 的原型來實現了。然而,Reflect 就是簡化了這個操作。

Reflect.defineProperty(target,key,desc)

該方法等同於 Object.defineProperty,用來爲對象定義屬性。注意:Object.defineProperty 將逐漸被淘汰,取而代之的是 Reflect.defineProperty .

Reflect.getOwnPropertyDescriptor(target,prop)

該方法基本等同於 Object.getOwnPropertyDescriptor() ,用於得到指定屬性的屬性描述符,將來後者將會被廢除。

Reflect.isExtensible(target)

對應 Object.isExtensible() ,返回一個布爾值,表示當前對象是否可擴展。

Reflect.preventExtensions(target)

對應 Object.preventExtensions() ,用於讓一個對象變爲不可擴展,返回一個布爾值,表示是否操作成功。

Reflect.ownKeys(target)

該方法用於返回對象的所有屬性,等於 Object.getOwnPropertyNamesObject.getOwnPropertySymbols 兩者之和。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章