Object方法與Reflect

本篇旨在梳理對象靜態方法,與此同時採用對比的方式介紹Reflect接口,在梳理過程當中當作學習筆記,若是對於讀者有幫助就更好了。數組

1、Object靜態方法與對應Reflect

一、遍歷對象屬性方法

  • for...in:非靜態方法,此處爲展現繼承效果,返回非Symbol類的繼承和自身屬性。
  • Object.keys(obj):返回一個數組,數組成員爲obj自身(非繼承)、可枚舉、非Symbol類型屬性名。
  • Object.values(obj):返回自身(非繼承)、可枚舉、非Symbol類型屬性的值。
  • Object.entries(obj):返回自身(非繼承)、可枚舉、非Symbol類型屬性的鍵值對數組。
  • Object.fromEntries(obj):Object.entries方法的逆操做,將一個鍵值對數組轉換爲對象。
  • Object.getOwnPropertyNames(obj):返回一個數組,數組成員爲obj自身屬性(非繼承)、非Symbol類型屬性名,與Object.keys()的區別在於返回數組成員包括不可枚舉屬性。
  • Object.getOwnPropertySymbols(obj):返回一個數組,數組成員爲obj自身全部的Symbol類型屬性名。
  • Reflect.ownKeys(obj):返回一個數組,數組成員爲obj自身全部的屬性,是Object.getOwnPropertyNames(obj)與Object.getOwnPropertySymbols(obj)結果集合。
// 定義三個Symbol類型屬性名
let [s1, s2, s3] = [Symbol(), Symbol(), Symbol()]
let parent = {
    k1: 'a',
    k2: 'b',
    [s1]: 's1',
    f1: function() {}
}

let child = {}

//child繼承parent
Object.setPrototypeOf(child, parent)

//爲child對象添加屬性及描述
Object.defineProperties(child, {
    k3: {
        value: 'c',
        enumerable: true
    },
    k4: {
        value: 'd',
        enumerable: false
    },
    [s2]: {
        value: 's2',
        enumerable: true
    },
    [s3]: {
        value: 's3',
        enumerable: false
    },
    f2: {
        value: function() {},
        enumerable: true
    }
})

//arr承載for...in 的屬性名
let arr = []

for (let key in child) {
    arr.push(key)
}

arr //  ["k3", "f2", "k1", "k2", "f1"]
Object.keys(child) //["k3", "f2"]
Object.values(child)//["c", ƒ]
Object.entries(child)//[["k3", "c"],["f2", ƒ]]
Object.getOwnPropertyNames(child) //["k3", "k4", "f2"]
Object.getOwnPropertySymbols(child) // [Symbol(), Symbol()]
Reflect.ownKeys(child) // ["k3", "k4", "f2", Symbol(), Symbol()]
複製代碼

二、對象模型方法

對象模型方法包括獲取屬性描述及定義屬性
bash

  • Object.getOwnPropertyDescriptor(obj , propertyKey):返回一個對象,對象爲obj屬性propertyKey描述。
  • Reflect.getOwnPropertyDescriptor(obj , propertyKey):返回一個對象,對象爲obj屬性propertyKey描述。未來會替代Object.getOwnPropertyDescriptor(obj,propertykey)。
  • Object.getOwnPropertyDescriptors(obj):返回一個對象,對象obj的所有屬性的描述。
  • Object.defineProperty(obj , propertyKey , attributes):在obj對象中添加屬性和屬性描述。
  • Reflect.defineProperty(obj , propertyKey , attributes):用法同Object.defineProperty(obj,propertykey,attributes),未來會替代Object.defineProperty(obj,propertykey,attributes)。
  • Object.defineProperties(obj , propertyKeys , attributes)經過描述對象,定義多個屬性。

注意:Object.defineProperty || Reflect.defineProperty || Object.defineProperties 定義屬性時,屬性描述沒有設置爲true的話,所有默認爲false
app

let obj = {}
//添加屬性描述
Object.defineProperty(obj, 'a', {
    value: "a",
    enumnerabl: true
})
//添加屬性描述
Reflect.defineProperty(obj, 'b', {
    value: "b",
    writable: true
})
//添加屬性描述
Object.defineProperties(obj, {
    'c': {
        value: 'c',
        configurable: true
    }
})
Object.getOwnPropertyDescriptor(obj, 'a')
//{value: "a", writable: false, enumerable: false, configurable: false}

Reflect.getOwnPropertyDescriptor(obj, 'a')
//{value: "a", writable: false, enumerable: false, configurable: false}
Object.getOwnPropertyDescriptors(obj)
/*a: {value: "a", writable: false, enumerable: false, configurable: false}
 b: {value: "b", writable: true, enumerable: false, configurable: false}
 c: {value: "c", writable: false, enumerable: false, configurable: true}*/複製代碼

三、控制對象方法

擴展--密封--凍結:對象控制程度依次加強
函數

  • Object.isExtensible(obj):判斷對象是否可擴展,返回布爾值。
  • Object.preventExtensions(obj):阻止對象obj擴展,其實就是阻止新增屬性,不影響修改已有屬性及刪除屬性。
let obj = {
    a: 'a',
    b: 'b'
}
Object.preventExtensions(obj)
Object.isExtensible(obj) //false複製代碼
  • Reflect.preventExtensions(obj):做用同Object.preventExtensions(obj)。
  • Reflect.isExtensible (obj):做用同Object.isExtensible(obj),區別在於若是參數不是對象,Object.isExtensible會返回false,由於非對象本是不可擴展的,而Reflect.isExtensible會報錯。
let obj = {
    a: 'a',
    b: 'b'
}
Reflect.preventExtensions(obj)
Reflect.isExtensible(obj) //false
複製代碼
  • Object.seal(obj):密封對象obj。除了修改已有屬性的值,其餘操做(修改已有屬性描述、新增屬性、刪除屬性)均不容許。
  • Object.isSealed(obj):判斷對象是否密封,返回布爾值。
let obj = {
    a: 'a',
    b: 'b'
}
Object.seal(obj)
Object.isSealed(obj) //true複製代碼
  • Object.freeze(obj):凍結對象,對象一旦凍結,屬性的操做所有不容許,換句話說,對象凍結,對象永不可變。
  • Object.isFrozen(obj):判斷一個對象是否被凍結,返回一個布爾值。
let obj = {
    a: 'a',
    b: 'b'
}
Object.freeze(obj)
Object.isFrozen(obj) //true複製代碼

四、原型鏈方法

該節主要介紹實例對象之間的繼承以及查看實例對象繼承源。學習

  • Object.create(proto [,propertiesObject]):使用指定的對象及其屬性建立一個新對象。Object.create生成的對象,動態繼承原型對象

proto:新建立對象的原型對象,能夠爲null。

propertiesObject:一個或多個屬性的描述。
ui

常常見到有文章用new命令與Object.create方法比較,我的理解new命令是建立夠構造函數的實例(Object自己就是個函數,能夠當成構造函數使用),而如何 從一個實例對象生成另一個實例對象呢,這個時候Object.create就應運而生了。

const parent = {
    print: function() {
        console.log("I am from parent")
    }
}
const child = Object.create(parent)
child.print() //I am from parent
複製代碼

class parent {
    constructor(x = 1, y = 2) {
        this.x = x;
        this.y = y
    }
    multi() {
        console.log(this.x * this.y)
    }
}

let child = new parent(3, 4)

let grandson = Object.create(child)
grandson.multi() //12複製代碼

  • Object.setPrototypeOf(obj , proto):設置該對象的原型。使用obj.__proto__設置爲proto,返回參數對象obj自己。
我的理解:Object.create()與Object.setPrototypeOf()兩種方法的差異在於:Object.create()利用原型對象生成一個新對象,而Object.setPrototype()是爲已有對象設置原型對象,在實際使用時,在不添加屬性集描述狀況下,二者沒有差異。
  • Reflect.setPrototypeOf(obj , proto):返回表示是否成功的布爾值,與Object.setPrototypeOf(obj , proto)對應,我的認爲未來Reflect.setPrototypeOf會替代Object.setPrototypeOf。
  • Object.getPropertypeOf(obj):讀取對象的__proto__屬性,返回對象obj的原型對象。
  • Reflect.getPrototypeOf(obj):與Object.getPrototypeOf(obj)對應,我的認爲未來Reflect.getPrototypeOf會替代Object.getPrototypeOf。
區別:若是參數不是對象,Object.getPrototypeOf會將這個參數轉爲對象,而後再運行,而Reflect.getPrototypeOf會報錯。

let a = { a: 'a' }
let b = Object.setPrototypeOf({}, a)
let c = Object.create(a)
//注意Reflect.setPrototypeOf(obj,proto)的使用
let d = {}
Reflect.setPrototypeOf(d, a)
Object.getPrototypeOf(b) //{a: "a"}
Reflect.getPrototypeOf(c) //{a: "a"}
Reflect.getPrototypeOf(d) //{a: "a"}複製代碼

  • Object.assign(target , source1 , ...):用於將全部可枚舉屬性的值從一個或多個源對象複製到目標對象,返回目標對象。

Object.assign方法複製的屬性有幾個點:非繼承、屬性可枚舉、同名覆蓋(前提是可枚舉)、Symbol類屬性惟一,最重要的是隻能淺拷貝this

let [s1, s2, s3] = [Symbol(), Symbol(), Symbol()]
let parent = {
    parent: 'parent',
    s1: 's1'
}
let child = Object.create(parent, {
    c1: {
        value: 'c1',
        enumbrable: true
    },
    c2: {
        value: 'c2',
        enumerable: false
    },
    c3: {
        value: 'c3',
        enumerable: true
    },
    [s2]: {
        value: 's2',
        enumerable: true
    },
    [s3]: {
        value: 's3',
        enumerable: true
    }
})
let c_assign = { c1: 'ca1', c2: 'ca2', [s2]: 'sa2', }
Object.assign(c_assign, child, { d: 'd' })
c_assign //{c1: "ca1", c2: "ca2", c3: "c3", d: "d", Symbol(): "s2", Symbol(): "s3"}複製代碼

2、Reflect實例對象方法

一、Reflect操做實例對象屬性方法

  • Reflect.has(obj , properKey):判斷實例對象obj是否存在屬性propertyKey,返回布爾值。
  • Reflect.deleteProperty(obj , propertyKey):等同於delete obj[propertyKey],刪除實例對象的屬性,返回布爾值。
  • Reflect.get(target , name [,receiver]):獲取屬性值的方法。

不設置receiver時,獲取target對象的屬性。若是target不是對象,報錯。
spa

receiver的功能能夠理解爲數據源,將數據源中的屬性值做用在target對象部署讀取函數的屬性上。target對象中存在兩個關鍵詞get和this
code

let o1 = {
    a: 1,
    b: 2,
    get sum() {
        return this.a + this.b
    }
}
let o2 = {
    a: 3,
    b: 4
}
Reflect.get(o1, 'a') //1
Reflect.get(o1, 'sum', o2) //7複製代碼
  • Reflect.set(target , propertyKey , value [,receiver]):設置實例對象target屬性propertyKey值爲value,若是設置receiver,則對於receiver中的屬性進行設值。

若是屬性propertyKey存在,則更改屬性propertyKey值爲value;若是屬性不存在,則新增一個屬性並賦值。
對象

當receiver存在時,能夠理解爲使用目標對象target中設置賦值函數的屬性propertyKey設置receiver中屬性值爲value。target對象中存在兩個關鍵詞set和this

另外,receiver中屬性在賦值函數中不存在時,爲receiver對象新增一個屬性,並賦值。

//展現效果
let o3 = {
    a: 1,
    set c(v) {
        this.a = v
    }
}
let o4 = {
    a: 0
}
Reflect.set(o3, 'a', 2) //o3.a=2
Reflect.set(o3, 'b', 3) //o3.b=3
Reflect.set(o3, 'c', 5, o4) //o4.a=五、o3.a=2複製代碼
let o3 = {
    a: 1,
    set c(v) {
        this.d = v
    }
}
let o4 = {
    a: 0
}
Reflect.set(o3, 'c', 5, o4) //o4.d=5複製代碼
//Reflect.set在Array上的使用
let arr = ['a', 'b', 'c']
Reflect.set(arr, 2, 'd') //arr=["a", "b", "d"]
Reflect.set(arr, 4, 'd') //arr= ["a", "b", "d", empty, "d"]
Reflect.set(arr, 'length', 2) //arr= ["a", "b"]複製代碼

二、Reflect函數綁定方法

  • Reflect.apply(fn , thisArg,args):指定的參數列表args向目標函數fn發起調用。

thisArg是函數fn調用時綁定的this對象。

args是調用時傳遞的類數組的對象參數列表

//爲了區分教程上案例
const fn = function(v) {
    let arr = Reflect.ownKeys(this)
    return arr[v]
}
let obj = {
    a: 'a',
    b: 'b',
    c: 'c'
}
Reflect.apply(fn, obj, [1]) //'b'複製代碼

三、Reflect調用構造函數方法

  • Reflect.construct(target , args):與new操做符同樣,來調用構造函數。

這個方法還有第三個參數,可選,暫時不涉及

function A(a) {
    this.b = a
}

let a = Reflect.construct(A, ['aa'])
//a={b:'aa'}複製代碼

3、後續

但願你們針對文中的內容多多指點,另外對於文章沒有提到的方法你們提出來,我也會後續進行更改和補充,謝謝你們。

相關文章
相關標籤/搜索