成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

講清楚之 javascript 對(duì)象屬性描述符

zhjx922 / 2615人閱讀

摘要:所以搞清楚是理解對(duì)象屬性描述符的唯一途徑。是一個(gè)對(duì)象,對(duì)象里的屬性描述符有兩種類型數(shù)據(jù)描述符和存取描述符。描述符必須是這兩種形式之一不能同時(shí)是兩者。描述符中未顯示設(shè)置的特性使用其默認(rèn)值。創(chuàng)建一個(gè)新屬性默認(rèn)描述符的鍵值都是或者。

對(duì)象屬性描述符

當(dāng)別人對(duì)你提及對(duì)象屬性描述符,可能會(huì)蒙逼。而如果提及對(duì)象屬性的 get/set 方法就秒懂了,標(biāo)準(zhǔn)描述和習(xí)慣表述在這里有些差別,但是指向的是同一個(gè)概念所涉及的東西。對(duì)象屬性描述符在編程實(shí)踐中是通過(guò) Object 對(duì)象的defineProperty方法暴露給我們。所以搞清楚Object.defineProperty是理解對(duì)象屬性描述符的唯一途徑。

Object.defineProperty, define Property 翻譯成中文就是定義屬性,顧名思義就是為對(duì)象定義或修改屬性的細(xì)節(jié),即通過(guò)屬性描述符來(lái)定義屬性讀寫(xiě)的細(xì)節(jié)。使用該方法允許精確添加或修改對(duì)象的屬性,熟悉 vue 的朋友對(duì) defineProperty 因該不陌生:

Object.defineProperty(obj, prop, descriptor)

defineProperty 接受3個(gè)參數(shù), obj 表示要修改或者定義屬性的對(duì)象,prop 是要定義或者修改屬性的名稱, descriptor 屬性描述符用于定義該屬性的特性。

descriptor 是一個(gè)對(duì)象,對(duì)象里的屬性描述符有兩種類型:數(shù)據(jù)描述符存取描述符。

數(shù)據(jù)描述符是一個(gè)具有值的屬性,該值可能是可寫(xiě)的,也可能不是可寫(xiě)的。

存取描述符是由getter-setter函數(shù)對(duì)描述的屬性。描述符必須是這兩種形式之一;不能同時(shí)是兩者。

數(shù)據(jù)描述符和存取描述符均具有一下可選鍵值(特性):

configurable: 如果為 false,則任何嘗試刪除目標(biāo)屬性或修改屬性以下特性(writable, configurable, enumerable)的行為將被無(wú)效化,默認(rèn)值為 false。

enumerable: 是否能枚舉。也就是是否能被for-in遍歷。默認(rèn)值為 false

writable: 是否能修改值。默認(rèn)為 false

value: 該屬性的具體值是多少。默認(rèn)為 undefined

存取描述符:

get: 目標(biāo)屬性被訪問(wèn)就會(huì)調(diào)回此方法,并將此方法的運(yùn)算結(jié)果返回用戶。默認(rèn)為 undefined

set: 目標(biāo)屬性被賦值,就會(huì)調(diào)回此方法。默認(rèn)為 undefined

描述符可同時(shí)具有的鍵值:

configurable enumerable value writable get set
數(shù)據(jù)描述符 Yes Yes Yes Yes No No
存取描述符 Yes Yes No No Yes Yes

如果一個(gè)描述符不具有value,writable,get 和 set 任意一個(gè)關(guān)鍵字,那么它將被認(rèn)為是一個(gè)數(shù)據(jù)描述符。如果一個(gè)描述符同時(shí)有(value或writable)和(get或set)關(guān)鍵字,將會(huì)產(chǎn)生一個(gè)異常。所以 value、writable 與 get/set 不能同時(shí)設(shè)置。

var obj = {}
obj.a = 123

Object.defineProperty(obj, "newDataProperty", {
    value: 101, // 設(shè)置值
    writable: true, // 值可以被修改
    enumerable: true, // 可以被枚舉
    configurable: true // 屬性可以被刪除、特性可以修改
})

上面給對(duì)象 obj 添加一個(gè)新屬性 "newDataProperty",并且設(shè)置了屬性的特性。

在ES5之前對(duì)象的屬性我們只能設(shè)置一個(gè)字面量值或者一個(gè)引用,在瀏覽器支持Object.defineProperty方法之后,就像給了我們一臺(tái)顯微鏡,能夠在更低的粒度層控制屬性的行為和特性:定義屬性的可訪問(wèn)行、值的讀寫(xiě)規(guī)則等。

如果對(duì)象中不存在指定的屬性,Object.defineProperty()會(huì)創(chuàng)建這個(gè)屬性。如果屬性已經(jīng)存在,Object.defineProperty()將嘗試根據(jù)描述符中的值以及對(duì)象當(dāng)前的配置來(lái)修改這個(gè)屬性。如果舊描述符將其configurable 屬性設(shè)置為false,則該屬性被認(rèn)為是“不可配置的”,并且沒(méi)有屬性可以被改變(除了單向改變 writable 為 false)。當(dāng)屬性不可配置時(shí),不能在數(shù)據(jù)和訪問(wèn)器屬性類型之間切換。

描述符中未顯示設(shè)置的特性使用其默認(rèn)值。

下面用幾個(gè)栗子來(lái)演示這些特性的具體表現(xiàn):

configurable
let foo = {
    a: 1
}
delete foo.a
Object.defineProperty(foo, "b", {
    value: 2, // 默認(rèn)值為2
    configurable: false // 不容許被刪除和修改
})
delete foo.b // 無(wú)法刪除
foo.b = 999 // 無(wú)法修改
console.log(foo.b) // 2 
enumerable
let foo = {
    a: 1,
    b: 2,
    c: 3
}
for (let i in foo) {
    // a、b、c可以被枚舉
    console.log(`key: ${i}, value: ${foo[i]}`)
}

Object.defineProperty(foo, "a", {
    enumerable: false // 設(shè)置屬性不可以被枚舉
})
for (let i in foo) {
    // a沒(méi)有被枚舉
    console.log(`key: ${i}, value: ${foo[i]}`)
}
writable
let foo = {
    a: 1
}
// 修改 foo.a 的值
foo.a = 2 
console.log(foo.a) // 2

Object.defineProperty(foo, "a", {
    writable: false // 設(shè)置值不能被修改
})
// 嘗試修改 foo.a 的值
foo.a = 3 // 無(wú)法修改
console.log(foo.a) // 2
value
let foo = {}
Object.defineProperty(foo, "a", {
    value: 1 // 設(shè)置屬性的值為 1
})
console.log(foo.a) // 1
get/set
let foo = {
    a: 1
}
Object.defineProperty(foo, "b", {
    get: function () {
        return `hi, ${this.value}`
    },
    set: function (value) {
        this.a = value // 將輸入值保存在同對(duì)象下屬性 a 里
        this.value = value + 1
    }
})
console.log(foo.b) // "hi, undefined"
foo.b = 1
console.log(foo.a) // 1
console.log(foo.b) // hi, 2

注意: get沒(méi)有參數(shù),set接受實(shí)參為當(dāng)前設(shè)置的值.。在get、set函數(shù)內(nèi)部可以通過(guò)this.value訪問(wèn)value特性,從而通過(guò)該特性來(lái)獲取或者著設(shè)置屬性的值。get/set 常用于值依賴內(nèi)部數(shù)據(jù)的場(chǎng)合。需要盡量同時(shí)設(shè)置get、set。如果僅僅只設(shè)置了get,那么我們將無(wú)法設(shè)置該屬性值。如果僅僅只設(shè)置了set,我們也無(wú)法讀取該屬性的值。

Object.defineProperty只能設(shè)置一個(gè)屬性的描述符,當(dāng)需要設(shè)置多個(gè)屬性描述符時(shí)可以使用Object.defineProperties

let foo = {}
Object.defineProperties(foo, {
    a: {
        value: 1,
        configurable: true
    },
    b: {
        get: function() {
            return this.value ? `hi, ${this.value}` : 0
        },
        set: function(value) {
            this.value = value + 1
        }
    }
})

console.log(foo.a) // 1
console.log(foo.b) // 0
foo.b = 2
console.log(foo.b) // "hi, 3"

我們可以通過(guò)Object.getOwnPropertyDescriptor獲取某一屬性的特性集合:

let foo = {
    a: 1
}
Object.defineProperty(foo, "a", {
    value: 2, // 設(shè)置值為 2
    writable: false, // 值不可修改
    configurable: false // 設(shè)置屬性不可刪除,特性不可修改
})
let fooDescripter = Object.getOwnPropertyDescriptor(foo, "a")

console.log(fooDescripter)
// 獲取的特性如下
// {
//   configurable:false,
//   enumerable:true,
//   value:2,
//   writable:false
// }

這里需要注意,Object.defineProperty創(chuàng)建一個(gè)對(duì)象的新屬性與修改一個(gè)已經(jīng)存在屬性的區(qū)別。創(chuàng)建一個(gè)新屬性默認(rèn)描述符的鍵值都是 false 或者 undefined。而修改一個(gè)已經(jīng)存在的屬性的描述符時(shí),如果之前沒(méi)有被設(shè)置過(guò)或過(guò)原始方式給對(duì)象添加的屬性,則屬性的 configurable、enumerable、writable 描述符都默認(rèn)為 true。具體差異舉個(gè)例子細(xì)細(xì)體會(huì):

let foo = {}
Object.defineProperty(foo, "a", {
    value: 2 // 設(shè)置值為 2
})
let fooDescripter = Object.getOwnPropertyDescriptor(foo, "a")

console.log(fooDescripter)
// 獲取的特性如下
// {
//   configurable:false, // 不容許被刪除和修改
//   enumerable: false, // 不能被枚舉
//   value:2,
//   writable:false // 值不可修改
// }

變量 a 是通過(guò) Object.defineProperty方法創(chuàng)建的,默認(rèn)所有屬性描述符的值都為 false。 我們可以通過(guò)最后兩個(gè)代碼示例體會(huì)一下區(qū)別:enumerable屬性描述符在兩個(gè)例子中都沒(méi)有被事先設(shè)置,但是不同情形下的值不一樣。

原則上這個(gè)系列不會(huì)去講某個(gè)API,但是屬性描述符能夠加深我們對(duì) javascript 、框架底層的理解。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/108021.html

相關(guān)文章

  • 講清楚之 javascript 變量對(duì)象

    摘要:示例代碼執(zhí)行上下文創(chuàng)建階段在這個(gè)階段上下文對(duì)象會(huì)生成,并創(chuàng)建變量對(duì)象創(chuàng)建作用域鏈確定的指向。全局對(duì)象是作用域鏈的頭,還意味著在頂層代碼中聲明的所有變量都將成為全局對(duì)象的屬性。 變量對(duì)象 這一節(jié)聊一下變量對(duì)象。都是干貨(^▽^) 變量對(duì)象是函數(shù)運(yùn)行時(shí)數(shù)據(jù)的集合,存儲(chǔ)了在上下文中定義的變量和函數(shù),不同的函數(shù)的變量對(duì)象稍有不同。 還是從上下文說(shuō)起,javascript 引擎執(zhí)行到函數(shù)的時(shí)候會(huì)...

    jeffrey_up 評(píng)論0 收藏0
  • 講清楚之 javascript 參數(shù)傳值

    摘要:講清楚之參數(shù)傳值參數(shù)傳值是指函數(shù)調(diào)用時(shí),給函數(shù)傳遞配置或運(yùn)行參數(shù)的行為,包括通過(guò)進(jìn)行傳值。所以對(duì)的賦值會(huì)改變上下文棧中標(biāo)識(shí)符保存的具體值此時(shí)如果使用的是按引用傳遞,則變量所指向的對(duì)象因該也被賦值為。 講清楚之 javascript 參數(shù)傳值 參數(shù)傳值是指函數(shù)調(diào)用時(shí),給函數(shù)傳遞配置或運(yùn)行參數(shù)的行為,包括通過(guò)call、apply 進(jìn)行傳值。 在實(shí)際開(kāi)發(fā)中,我們總結(jié)javascript參數(shù)傳...

    itvincent 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<