首先我們得先知道,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
這樣就好了