????????該方法會(huì)直接在一個(gè)對(duì)象上定義一個(gè)新屬性额衙,或者修改一個(gè)對(duì)象的現(xiàn)有屬性,并返回此對(duì)象怕吴。應(yīng)當(dāng)直接在object構(gòu)造器上調(diào)用此方法入偷,而不是在任意一個(gè)object類型的實(shí)例上調(diào)用。
Object.defineProperty(obj, prop, descriptor)
參數(shù):
obj:要定義屬性的對(duì)象
prop:要定義或修改的屬性名稱或symbol
descriptor:要定義或修改的屬性描述符
????????對(duì)象里目前存在的屬性描述符有兩種主要形式:數(shù)據(jù)描述符和存取描述符械哟。數(shù)據(jù)描述符是一個(gè)具有值的屬性,該值可以是可寫的殿雪,也可以是不可寫的暇咆。存取描述符是由getter函數(shù)和setter函數(shù)所描述的屬性。一個(gè)描述符只能是這兩者其中之一丙曙,不能同時(shí)是兩者爸业。
左對(duì)齊 | 右對(duì)齊 | 居中對(duì)齊 |
---|---|---|
單元格 | 單元格 | 單元格 |
單元格 | 單元格 | 單元格 |
屬性名 | configurable | enumerable | value | writable | get | Set |
---|---|---|---|---|---|---|
作用 | 是否可配置對(duì)象(刪除屬性) | 是否可枚舉 | 是否可以修改對(duì)象 | 獲取obj.key | 將修改的值重新賦值 | |
默認(rèn)值 | false | false(也就是object.defineproperty定義的屬性默認(rèn)是不能被遍歷的) | undefined | false | undefined | undefined |
數(shù)據(jù)描述符 | 可有 | 可有 | 可有 | 可有 | 不可有 | 不可有 |
存取描述符 | 可有 | 可有 | 不可有 | 不可有 | 可有 | 可有 |
Object.defineProperty(obj, key, {
// 1.value
enumerable: true, // 4.可以枚舉
configurable: true, // 2.可以配置對(duì)象,刪除屬性
// writable: true // 3.可以修改對(duì)象
// get亏镰,set設(shè)置時(shí)不能設(shè)置writable和value,它們代替了 二者是互斥的 可以去看數(shù)據(jù)描述符和存取描述符
// 5.獲取obj.key的時(shí)候就會(huì)調(diào)用get方法
get: function reactiveGetter () {
const value = getter ? getter.call(obj) : val
if (Dep.target) {
dep.depend()
if (childOb) {
childOb.dep.depend()
if (Array.isArray(value)) {
dependArray(value)
}
}
}
return value
},
// 6.將修改的值重新賦值
// 當(dāng)我們更新data的時(shí)候,會(huì)觸發(fā)set方法炕横,執(zhí)行dep.notify()方法
set: function reactiveSetter (newVal) {
const value = getter ? getter.call(obj) : val
/* eslint-disable no-self-compare */
if (newVal === value || (newVal !== newVal && value !== value)) {
return
}
/* eslint-enable no-self-compare */
if (process.env.NODE_ENV !== 'production' && customSetter) {
customSetter()
}
// #7981: for accessor properties without setter
if (getter && !setter) return
if (setter) {
setter.call(obj, newVal)
} else {
val = newVal
}
childOb = !shallow && observe(newVal)
dep.notify()
}
})