摘要:可枚舉性屬性是一個布爾值,表示目標屬性是否可枚舉。可配置性返回一個布爾值,決定了是否可以修改屬性描述對象。其中,存值函數稱為,使用屬性描述對象的屬性取值函數稱為,使用屬性描述對象的屬性。
JavaScript 提供了一個內部數據結構,用來描述對象的屬性,控制它的行為,比如該屬性是否可寫、可枚舉等等。這個內部數據結構稱為“屬性描述對象”(attributes object)。每個屬性都有自己對應的屬性描述對象,保存該屬性的一些元信息。
元屬性屬性描述對象的各個屬性稱為“元屬性”,因為它們可以看作是控制屬性的屬性。
valuevalue 屬性是目標屬性的值。
var obj = { p : 123 }; Object.getOwnPropertyDescriptor(obj, "p").value // 123 Object.defineProperty(obj, "p", { value: 246 }); obj.p // 246
改寫 value 屬性時,只要 writable 和 configurable 有一個為 true,就允許改動。只有 writable 和 configurable 兩個都為 false 時,value 屬性才不可改寫。
var obj = Object.defineProperty({}, "p", { value: 1, writable: false, configurable: false }); Object.defineProperty(obj, "p", {value: 2}) // TypeError: Cannot redefine property: p obj.p = 4 obj.p // 1
value 屬性不可改寫時,直接屬性賦值,不報錯,但不會成功。在嚴格模式下會報錯,即使對屬性重新賦予一個同樣的值。
writablewritable 屬性是一個布爾值,決定了目標屬性的值 value 是否可以被改變。
var obj = {}; Object.defineProperty(obj, "a", { value: 37, writable: false }); obj.a // 37 obj.a = 25; obj.a // 37
如果原型對象的某個屬性的 writable 為 false,那么子對象將無法自定義這個屬性。
var proto = Object.defineProperty({}, "foo", { value: "a", writable: false }); var obj = Object.create(proto); obj.foo = "b"; obj.foo // "a"
但是,有一個規避方法,就是通過覆蓋屬性描述對象,繞過這個限制。原因是這種情況下,原型鏈會被完全忽視。
Object.defineProperty(obj, "foo", { value: "b" }); obj.foo // "b"enumerable
enumerable (可枚舉性)屬性是一個布爾值,表示目標屬性是否可枚舉。
如果一個屬性的 enumerable 為 false 時,下面四個操作將不會取到該屬性。
for..in 循環
Object.keys() 方法
JSON.stringify() 方法
Object.assign():只拷貝對象自身的可枚舉的屬性。
var obj = {}; Object.defineProperty(obj, "x", { value: 123, enumerable: false }); obj.x // 123 for (var key in obj) {console.log(key);} // undefined Object.keys(obj) // [] JSON.stringify(obj) // "{}"
JSON.stringify 方法會排除 enumerable 為 false 的屬性,如果對象的 JSON 格式輸出要排除某些屬性,就可以利用這一點把這些屬性的 enumerable 設為 false。
configurableconfigurable (可配置性)返回一個布爾值,決定了是否可以修改屬性描述對象。也就是說,configurable 為 false 時,value、writable、enumerable 和 configurable 都不能被修改了。
var obj = Object.defineProperty({}, "p", { value: 1, writable: false, enumerable: false, configurable: false }); Object.defineProperty(obj, "p", {value: 2}) // TypeError: Cannot redefine property: p Object.defineProperty(obj, "p", {writable: true}) // TypeError: Cannot redefine property: p Object.defineProperty(obj, "p", {enumerable: true}) // TypeError: Cannot redefine property: p Object.defineProperty(obj, "p", {configurable: true}) // TypeError: Cannot redefine property: p
注意,writable 只有在 false 改為 true 時會報錯,true 改為 false 是允許的。
var obj = Object.defineProperty({}, "p", { writable: true, configurable: false }); Object.defineProperty(obj, "p", {writable: false}) // 修改成功
可配置性決定了目標屬性是否可以被刪除(delete)。configurable 為 true 時,屬性可以被刪除,為 false 時,屬性不可被刪除。
var obj = Object.defineProperties({}, { p1: { value: 1, configurable: true }, p2: { value: 2, configurable: false } }); delete obj.p1 // true delete obj.p2 // false obj.p1 // undefined obj.p2 // 2存取器
除了直接定義以外,屬性還可以用存取器(accessor)定義。其中,存值函數稱為 setter,使用屬性描述對象的 set 屬性;取值函數稱為 getter,使用屬性描述對象的 get 屬性。
一旦對目標屬性定義了存取器,那么存取的時候,都將執行對應的函數。利用這個功能,可以實現許多高級特性,比如某個屬性禁止賦值。
var obj = Object.defineProperty({}, "p", { get: function () { return "getter"; }, set: function (value) { console.log("setter: " + value); } }); obj.p // "getter" obj.p = 123 // "setter: 123"
一旦定義了取值函數 get 或存值函數 set,就不能同時定義 writable 屬性或 value 屬性,否則會報錯。如果通過 Object.defineProperty() 重定義 writable 屬性或 value 屬性,那么取值函數 get 和存值函數 set 將會被 value 和 writable 覆蓋。
var obj = Object.defineProperty({}, "p", { get: function () { return "getter"; }, set: function (value) { console.log("setter: " + value); }, configurable: true }); Object.getOwnPropertyDescriptor(obj,"p") // { get: ? (), // set: ? (value), // enumerable: false, // configurable: true // } // 重定義 Object.defineProperty(obj, "p", { writable:true }); Object.getOwnPropertyDescriptor(obj,"p") // {value: undefined, writable: true, enumerable: false, configurable: true}
JavaScript 還提供了存取器的另一種寫法。與定義屬性描述對象是等價的,而且使用更廣泛。
var obj = { get p() { return "getter"; }, set p(value) { console.log("setter: " + value); } };
注意,取值函數 get 不能接受參數,存值函數 set 只能接受一個參數(即屬性的值)。
存取器往往用于,屬性的值依賴對象內部數據的場合。
var obj ={ $n : 5, get next() { return this.$n }, set next(n) { if (n >= this.$n) this.$n = n; else throw new Error("新的值必須大于當前值"); } }; obj.next // 5 obj.next = 10; obj.next // 10 obj.next = 5; // Uncaught Error: 新的值必須大于當前值與屬性描述對象相關的方法 1. Object.getOwnPropertyDescriptor()
Object.getOwnPropertyDescriptor() 可以獲取某個屬性的屬性描述對象。它的第一個參數是對象,第二個參數是對象的某個屬性名。返回的是該屬性的屬性描述對象。
var obj = { p1: "a", p2: "b"}; Object.getOwnPropertyDescriptor(obj, "p1") // { value: "a", // writable: true, // enumerable: true, // configurable: true // }
只能用于對象自身的(非繼承的)屬性。繼承的或不存在的屬性返回 undefined。
Object.getOwnPropertyDescriptor(obj, "toString") // undefined2. Object.getOwnPropertyDescriptors()
Object.getOwnPropertyDescriptors() 可以獲取參數對象的所有屬性的屬性描述對象。ES2017 引入標準。
Object.getOwnPropertyDescriptors(obj) // { p1: {value: "a", writable: true, enumerable: true, configurable: true} // p2: {value: "b", writable: true, enumerable: true, configurable: true} // }3. Object.defineProperty()
Object.defineProperty() 方法允許通過屬性描述對象,定義或修改一個屬性,然后返回修改后的描述對象。
Object.defineProperty(object, propertyName, attributesObject)
Object.defineProperty() 方法接受三個參數,依次如下。
object:屬性所在的對象
propertyName:字符串,表示屬性名
attributesObject:屬性描述對象
var obj = Object.defineProperty({}, "p", { value: 123, writable: false, enumerable: true, configurable: false }); obj.p // 123 obj.p = 246; obj.p // 123
注意,上例中第一個參數是{ }(一個新建的空對象),p屬性直接定義在這個空對象上面,然后返回這個對象,這是 Object.defineProperty() 的常見用法。
如果屬性已經存在,Object.defineProperty() 方法相當于更新該屬性的屬性描述對象。
4. Object.defineProperties()Object.defineProperties() 方法可以定義或修改多個屬性。接受兩個參數。
var obj = Object.defineProperties({}, { p1: { value: 123, enumerable: true }, p2: { value: "abc", enumerable: true }, p3: { get: function () { return this.p1 + this.p2 }, enumerable:true, configurable:true } }); obj.p1 // 123 obj.p2 // "abc" obj.p3 // "123abc"
元屬性默認值
Object.defineProperty() 和 Object.defineProperties() 參數里面的屬性描述對象,writable、configurable、enumerable 這三個屬性的默認值都為 false。
var obj = {}; Object.defineProperty(obj, "foo", {}); Object.getOwnPropertyDescriptor(obj, "foo") // { // value: undefined, // writable: false, // enumerable: false, // configurable: false // }5. Object.prototype.propertyIsEnumerable()
實例對象的 propertyIsEnumerable() 方法返回一個布爾值,用來判斷某個屬性是否可枚舉。
var obj = {}; obj.p = 123; obj.propertyIsEnumerable("p") // true obj.propertyIsEnumerable("toString") // false
注意,這個方法只能用于判斷對象自身的屬性,對于繼承的屬性一律返回 false。
參考鏈接:JavaScript 教程 屬性描述對象
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/99674.html
摘要:面向對象面向對象編程的全稱為簡稱。面向對象編程是用抽象方式創建基于現實世界模型的一種編程方式。面向對象編程可以看做是使用一系列對象相互協作的軟件設計。面向對象編程的三個主要特征是封裝繼承多態。 面向對象 面向對象編程的全稱為Object Oriented Programming,簡稱OOP。面向對象編程是用抽象方式創建基于現實世界模型的一種編程方式。面向對象編程可以看做是使用一系列對象...
摘要:默認為當該屬性的為時,才能被賦值運算符改變。可以是任何有效的值數值,對象,函數等。而這些篡改可能會影響對象的內置屬性或方法,從而導致對象的正常功能可能無法使用。 屬性描述符 JavaScript提供了一個內部數據結構,用于描述對象的值,控制其行為,例如該屬性是否可寫、是否可配置、是否可修改以及是否可枚舉等。這個內部數據結構被稱為‘屬性描述符’。每個屬性都有自己對應的屬性描述符,保存該屬...
摘要:數據描述符具有以下可選值該屬性對應的值。可以使任何有效的值數值,對象,函數。當且僅當該屬性的為時,該屬性才能出現在對象的枚舉屬性中默認為。凍結對象禁止對對象執行任何修改操作。張無忌凍結對象周芷若 Object類型 操作對象的屬性 屬性描述符 JavaScript提供了一個內部數據結構,用于描述對象的值,控制其行為,例如該屬性是否可寫,是否可配置,是否可修改以及是否可枚舉等。這個內部數據...
摘要:所以搞清楚是理解對象屬性描述符的唯一途徑。是一個對象,對象里的屬性描述符有兩種類型數據描述符和存取描述符。描述符必須是這兩種形式之一不能同時是兩者。描述符中未顯示設置的特性使用其默認值。創建一個新屬性默認描述符的鍵值都是或者。 對象屬性描述符 當別人對你提及對象屬性描述符,可能會蒙逼。而如果提及對象屬性的 get/set 方法就秒懂了,標準描述和習慣表述在這里有些差別,但是指向的是同一...
閱讀 3298·2023-04-26 02:40
閱讀 4651·2021-09-22 15:22
閱讀 1591·2021-09-22 10:02
閱讀 3485·2021-08-11 10:23
閱讀 1394·2019-08-30 15:55
閱讀 2496·2019-08-30 12:48
閱讀 590·2019-08-30 11:04
閱讀 705·2019-08-29 16:29