ECMA-262第5版在定義只有內部才用的特性(attribute)時,描述了屬性(property)的各種特徵。ECMA-262定義這些特性是爲了實現javascript引擎用的,因此在javascript中不能直接訪問它們。爲了表示特性時內部值,該規範把它們放在了兩對方括號中,例如[[Enumerable]]。
數據屬性
數據屬性包含一個數據值的位置,在這個位置可以讀取和寫入值。數據屬性有4個描述其行爲的特性
類別
Value
包含這個屬性的數據值。讀取屬性值的時候,從這個位置讀取,寫入值得時候,把新值保存在這個位置。這個特性得默認值爲undefined
Configurable
表示能否通過delete刪除屬性從而重新定義屬性,能否修改屬性的特性,或者能否把屬性修改爲訪問器屬性。直接在對象上定義的屬性,它們的這個特性默認值爲true
Enumerable
表示能否通過for-in循環返回屬性,直接在對象上定義的屬性,它們的這個特性默認值爲true
Writable
表示能否修改屬性的值,直接在對象上定義的屬性,它們的這個特性默認值爲true
修改
要修改默認的特性,必須使用ES5的Object.defineProperty()方法
// 使用方式 Object.defineProperty( obj, prop, descriptor) obj:需要定義屬性的對象。 prop:需定義或修改的屬性的名字。 descriptor:一個包含設置特性的對象 // 例子 var person = {name: "percy"}; Object.defineProperty(person,"name",{ writable: false });
讀取
通過,Object.getOwnPropertyDescriptor()方法獲取指定對象上一個自有屬性對應的屬性描述符。(自有屬性指的是直接賦予該對象的屬性,不需要從原型鏈上進行查找的屬性)
var girl = {name: "zyj"}; console.log(Object.getOwnPropertyDescriptor(girl,"name")); // Object {value: "zyj", writable: true, enumerable: true, configurable: true}
注意⚠️
- 直接在對象上定義的屬性,它們的[[Configurable]]、[[Enumerable]]、[[Writable]]特性都被設置爲true,[[Value]]特性被設置爲了指定的值.
訪問器屬性
訪問器屬性不包含數據值,它們包含一對getter和setter函數(這兩個函數都不是必須的)。在讀取訪問器屬性時會調用getter函數,這個函數會負責返回有效的值,在寫入訪問器屬性時,會調用setter函數並傳入新值。這個函數負責決定如何處理數據。訪問器屬性有如下4個特性
類別
Configurable
表示能否通過delete刪除屬性從而重新定義屬性,能否修改屬性的特性,或者能否把屬性修改爲數據屬性。直接在對象上定義的屬性,這個特性的默認值爲true
Enumerable
表示能否通過for-in循環返回屬性。直接在對象上定義的屬性,這個特性的默認值爲true
Get
在讀取屬性時調用的函數。默認值爲undefined
Set
在寫入屬性時調用的函數。默認值爲undefined
定義
訪問器屬性不能直接定義,必須使用Object.defineProperty()定義單個或者Object.defineProperties()來定義
定義單個。注意⚠️:用Object.defineProperty()定義的訪問器屬性,其configurable和enumerable默認爲false。
var book = { year : 2004, edition : 1 }; Object.defineProperty(book,"year",{ get : function () { alert(this.year); }, set : function (newValue) { if (newValue > 2004) { this.year = newValue; this.edition += newValue - 2004; } } }); book.year; // 彈出窗口,顯示 2004 book.year = 2005; console.log(book.edition); // 2
定義多個
var obj = {}; Object.defineProperties(obj, { "property1": { value: true, writable: true }, "property2": { value: "Hello", writable: false } });
讀取
通過,Object.getOwnPropertyDescriptor()方法獲取指定對象上一個自有屬性對應的屬性描述符。(自有屬性指的是直接賦予該對象的屬性,不需要從原型鏈上進行查找的屬性)
var descriptor = Object.getOwnPropertyDescriptor(girl,"age"); console.log(descriptor.value); // 22 console.log(descriptor.configurable); // false console.log(descriptor.writable); // true console.log(descriptor.get); // undefined console.log(descriptor.set); // undefined
注意⚠️
用Object.defineProperty()定義的訪問器屬性,其configurable和enumerable默認爲false。
數據屬性和訪問器屬性互相轉化
數據屬性 -> 訪問器屬性
屬性的特性只能是訪問器描述符和數據描述符中的一種,給已有的數據屬性加get或set轉換爲訪問器屬性時,其屬性的value、writable就會被廢棄。
// 設置get和set其中任意一個即可轉換爲訪問器屬性 Object.defineProperty(person, "year", { get: function() { return this._year; }, set: function(value) { this._year= value; } }) var descriptor = Object.getOwnPropertyDescriptor(person, 'year'); console.log(descriptor); // {get: ƒ, set: ƒ, enumerable: true, configurable: true}
訪問器屬性 -> 數據屬性
將訪問器屬性轉換爲數據屬性,只需要給現有訪問器屬性設置value或writable這兩個屬性描述符中的任意一個即可,其原有的get和set就會被廢棄,從而轉換爲數據屬性。
注意⚠️:可以在訪問器屬性和數據屬性間相互轉化的屬性其configurable特性值必須爲true。configurable爲false,則不可以將其轉換爲數據屬性。
Object.defineProperty(person, "job", { configurable: true, enumerable: true, get: function() { return this._job; }, set: function(value) { this._job = value; } }); // 設置value和writable其中任意一個即可轉換爲數據屬性 Object.defineProperty(person, "job", { value: 'worker', writable: true }); var descriptor = Object.getOwnPropertyDescriptor(person, 'job'); console.log(descriptor); // {value: "worker", writable: true, enumerable: true, configurable: true}
擴展:如何定義對象
定義對象一共有如下四種方式
- 使用語法結構創建的對象
- 使用構造器創建的對象
- 使用 Object.create 創建的對象
- 使用 class 關鍵字創建的對象
下面我們分別來給個例子🌰
使用語法結構創建對象
var o = {a: 1};
使用構造器創建對象
function Graph() { this.vertices = []; this.edges = []; } var g = new Graph();
使用 Object.create 創建對象
var a = {a: 1}; var b = Object.create(a);
使用 class 關鍵字創建的對象
class Polygon { constructor(height, width) { this.height = height; this.width = width; } } let polygon = new Polygon();
參考
MDN文檔
https://blog.csdn.net/weixin_43936704/article/details/103930693https://www.cnblogs.com/he-ming-min/p/11011402.htmlhttps://www.cnblogs.com/absolute-child/p/7188417.htmlhttps://www.cnblogs.com/shiningly/p/9482283.html?utm_source=debugrun&utm_medium=referral