国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

講清楚之 javascript 對象屬性描述符

zhjx922 / 2610人閱讀

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

對象屬性描述符

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

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

Object.defineProperty(obj, prop, descriptor)

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

descriptor 是一個對象,對象里的屬性描述符有兩種類型:數據描述符存取描述符

數據描述符是一個具有值的屬性,該值可能是可寫的,也可能不是可寫的。

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

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

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

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

writable: 是否能修改值。默認為 false

value: 該屬性的具體值是多少。默認為 undefined

存取描述符:

get: 目標屬性被訪問就會調回此方法,并將此方法的運算結果返回用戶。默認為 undefined

set: 目標屬性被賦值,就會調回此方法。默認為 undefined

描述符可同時具有的鍵值:

configurable enumerable value writable get set
數據描述符 Yes Yes Yes Yes No No
存取描述符 Yes Yes No No Yes Yes

如果一個描述符不具有value,writable,get 和 set 任意一個關鍵字,那么它將被認為是一個數據描述符。如果一個描述符同時有(value或writable)和(get或set)關鍵字,將會產生一個異常。所以 value、writable 與 get/set 不能同時設置。

var obj = {}
obj.a = 123

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

上面給對象 obj 添加一個新屬性 "newDataProperty",并且設置了屬性的特性。

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

如果對象中不存在指定的屬性,Object.defineProperty()會創建這個屬性。如果屬性已經存在,Object.defineProperty()將嘗試根據描述符中的值以及對象當前的配置來修改這個屬性。如果舊描述符將其configurable 屬性設置為false,則該屬性被認為是“不可配置的”,并且沒有屬性可以被改變(除了單向改變 writable 為 false)。當屬性不可配置時,不能在數據和訪問器屬性類型之間切換。

描述符中未顯示設置的特性使用其默認值。

下面用幾個栗子來演示這些特性的具體表現:

configurable
let foo = {
    a: 1
}
delete foo.a
Object.defineProperty(foo, "b", {
    value: 2, // 默認值為2
    configurable: false // 不容許被刪除和修改
})
delete foo.b // 無法刪除
foo.b = 999 // 無法修改
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 // 設置屬性不可以被枚舉
})
for (let i in foo) {
    // a沒有被枚舉
    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 // 設置值不能被修改
})
// 嘗試修改 foo.a 的值
foo.a = 3 // 無法修改
console.log(foo.a) // 2
value
let foo = {}
Object.defineProperty(foo, "a", {
    value: 1 // 設置屬性的值為 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 // 將輸入值保存在同對象下屬性 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沒有參數,set接受實參為當前設置的值.。在get、set函數內部可以通過this.value訪問value特性,從而通過該特性來獲取或者著設置屬性的值。get/set 常用于值依賴內部數據的場合。需要盡量同時設置get、set。如果僅僅只設置了get,那么我們將無法設置該屬性值。如果僅僅只設置了set,我們也無法讀取該屬性的值。

Object.defineProperty只能設置一個屬性的描述符,當需要設置多個屬性描述符時可以使用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"

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

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

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

這里需要注意,Object.defineProperty創建一個對象的新屬性與修改一個已經存在屬性的區別。創建一個新屬性默認描述符的鍵值都是 false 或者 undefined。而修改一個已經存在的屬性的描述符時,如果之前沒有被設置過或過原始方式給對象添加的屬性,則屬性的 configurable、enumerable、writable 描述符都默認為 true。具體差異舉個例子細細體會:

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

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

變量 a 是通過 Object.defineProperty方法創建的,默認所有屬性描述符的值都為 false。 我們可以通過最后兩個代碼示例體會一下區別:enumerable屬性描述符在兩個例子中都沒有被事先設置,但是不同情形下的值不一樣。

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

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/108021.html

相關文章

  • 講清楚之 javascript 變量對象

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

    jeffrey_up 評論0 收藏0
  • 講清楚之 javascript 參數傳值

    摘要:講清楚之參數傳值參數傳值是指函數調用時,給函數傳遞配置或運行參數的行為,包括通過進行傳值。所以對的賦值會改變上下文棧中標識符保存的具體值此時如果使用的是按引用傳遞,則變量所指向的對象因該也被賦值為。 講清楚之 javascript 參數傳值 參數傳值是指函數調用時,給函數傳遞配置或運行參數的行為,包括通過call、apply 進行傳值。 在實際開發中,我們總結javascript參數傳...

    itvincent 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<