關(guān)于 Object.defineProperty() 小結(jié)

首先我們得先知道,ECMAScript中有兩種屬性:數(shù)據(jù)屬性和訪問(wèn)器屬性.

數(shù)據(jù)屬性

。

。

接下來(lái)我們看看例子

var person = {
      
}

我們要是想修改默認(rèn)屬性的值該怎么做呢?這時(shí)候就要用到標(biāo)題上所說(shuō)的方法了

Object.defineProperty(obj,prop,descriptor)

。obj:需要定義的屬性的對(duì)象
。prop:需要定義(創(chuàng)建)或修改的屬性的名字
。descriptor:需要定義或修改的屬性的描述符,可以是一個(gè)對(duì)象

var person = {
    
}
# 這里我們把這些數(shù)據(jù)屬性顯示的寫(xiě)了出來(lái)
Object.defineProperty(person,'a',{
    configurable:true,//可以修改默認(rèn)屬性
    enumerable:true,//可以被枚舉
    writable:true,//可以修改這個(gè)屬性的值
    value:1//定義一個(gè)初始的值為1
})
console.log(person)//Object {a: 1}
person.a=2
console.log(person)//Object {a: 2}
for(var k in person){
    console.log(k)//a,可以被枚舉
}

現(xiàn)在我們來(lái)修改一下默認(rèn)的值

Object.defineProperty(person,'a',{
    configurable:true,
    enumerable:false,
    writable:false,
    value:1
})
console.log(person)//Object {a: 1}
person.a=2
console.log(person)//Object {a: 1} 因?yàn)閣ritable值被設(shè)置為false了,所以不可以寫(xiě),嚴(yán)格模式下會(huì)報(bào)錯(cuò)
for(var k in person){
    console.log(k)//不起作用,因?yàn)閑numerable的值被設(shè)置為false了
}

我們?cè)囋嚢蒫onfigurable的值改為false

Object.defineProperty(person,'a',{
    configurable:false,//為false的時(shí)候不允許修改默認(rèn)屬性了
})
===============================
# 改為false之后再試試修改其他屬性
Object.defineProperty(person,'a',{
    configurable:true,
    enumerable:true,
    writable:true,
    value:1
})
//woa,控制臺(tái)直接報(bào)錯(cuò)了!連想把false值改回true都不行!也就是說(shuō),這個(gè)改動(dòng)是一次性了!
//也就是說(shuō),你可以使用Object.defineProperty()方法無(wú)限修改同一個(gè)屬性,但是當(dāng)把configurable改為false之后就有限制了

接下來(lái)我們看看訪問(wèn)器屬性
訪問(wèn)器屬性


。
。[[Get]]在讀取屬性時(shí)調(diào)用的函數(shù),默認(rèn)值為undefined
。[[Set]]在設(shè)置屬性的時(shí)候調(diào)用的函數(shù),默認(rèn)值為undefined

訪問(wèn)器屬性不能直接定義!只能通過(guò)Object.defineProperty()來(lái)定義

我們看看例子

var person = {
    a:1
  }
  Object.defineProperty(person,'a',{
    get(){
        return 3 //當(dāng)訪問(wèn)這個(gè)屬性的時(shí)候返回3
    },
    set(val){
        console.log(val)//當(dāng)設(shè)置這個(gè)屬性的時(shí)候執(zhí)行,val是設(shè)置的值
    }
})

person.a// 3,我們明明寫(xiě)的是a:1,怎么返回的3呢?這就是get()的威力了
person.a = 5// 5,相應(yīng)的設(shè)置的時(shí)候執(zhí)行了set()函數(shù)

我們來(lái)模擬一個(gè)訪問(wèn)和設(shè)置的默認(rèn)行為

var person = {
    a:1
}
# 注:里面的this指向ogj(person)
Object.defineProperty(person,'a',{
    get(){
        return this.a 
    },
    set(val){
        this.a = val 
    }
})
//我們想當(dāng)然的這么寫(xiě).
person.a//Uncaught RangeError: Maximum call stack size exceeded
什么,溢出了?這是為什么?
哦~原來(lái)是這么寫(xiě)的話會(huì)造成循環(huán)引用,狂call不止
我們看下流程:
person.a → get.call(person) → this.a → person.a  → get.call(person) → this.a......

我們得改一下

var person = {
    a:1
}
Object.defineProperty(person,'a',{
    get(){
        return this._a || 1 //定義一個(gè)新的屬性和一個(gè)默認(rèn)值
    },
    set(val){
        this._a = val 
    }
})
person.a// 1
person.a=2// 2
person.a// 2
這樣就好了

小結(jié)

當(dāng)把configurable值設(shè)置為false后,就不能修改任何屬性了,包括自己本身這個(gè)屬性
想用訪問(wèn)器屬性模擬默認(rèn)行為的話,必須得在里面新頂一個(gè)屬性,不然的話會(huì)造成循環(huán)引用
這對(duì)我們了解對(duì)象的工作機(jī)制很有作用,雖然可能很少會(huì)用到
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容