深入理解物件的資料屬性與訪問器屬性
建立物件的方式有兩種:第一種,透過new運算子後面跟Object建構函式,第二種,物件字面量方式。如下
var person = new Object(); person.name = 'Nicy'; person.age = 21; person.sayName = function() { console.log(this.name); }; var person = { name: 'Nicy', age: 21, sayName: function() { console.log(this.name); } }
這兩種方式建立出來的物件是一樣的,有相同的屬性和方法。這些屬性內部都有描述其行為的屬性描述符。
Object.defineProperty()
透過Object.defineProperty() 可以直接在物件上建立一個屬性,也可以修改已有的屬性。
Object.defineProperty(obj, prop, descriptor) 接收三個引數:
obj:屬性所在的物件
prop:要訪問的屬性名
descriptor:描述符物件
描述符物件包含六個屬性:configurable、enumerable、writable、value、get、set ,要修改屬性的特性,必須使用Object.defineProperty()方法。
透過以上兩種方式新增的物件屬性,其布林值特性預設值是true,透過Object.defineProperty來修改屬性特性時,只設定需要修改的特性即可;而透過Object.defineProperty建立的屬性,其布林值特性預設值是false。
ECMAScript中屬性分為兩種:資料屬性和訪問器屬性。
資料屬性
資料屬性包含四個屬性描述符:
[[Configurable]] : 表示能否透過delete刪除屬性從而重新定義屬性,能否修改屬性特性,能否把屬性修改為訪問器屬性。透過以上方式新增的物件屬性,預設為true。
[[Enumerable]] : 表示能否透過for-in 迴圈訪問屬性。透過以上方式新增的物件屬性,預設為true。
[[Writable]] : 表示能否修改屬性的值。透過以上方式新增的物件屬性,預設為true。
[[Value]] : 包含這個屬性的資料值,可讀取寫入。透過以上方式新增的物件屬性,預設為undefined。
Writable
var person = {}; Object.defineProperty(person, "name", { value: 'Nicy'}) person.name = 'Lee'; console.log(person.name) // 'Nicy'Object.defineProperty(person, "name", { writable: true}) person.name = 'Lee'; console.log(person.name) // 'Lee'
Object.defineProperty直接建立的屬性writable預設為false,value值不可修改,此時修改name為Lee,在非嚴格模式下不會報錯,但操作被忽略,在嚴格模式下會報錯。
Configurable
var person = { name: 'Nicy', age: 21, sayName: function() { console.log(this.name); } } Object.defineProperty(person, "name", { configurable: false})delete person.name; // 操作被忽略,無法透過delete刪除屬性 Object.defineProperty(person, "name", { // throw error configurable:true }) Object.defineProperty(person, "name", { // throw error enumerable: false}) Object.defineProperty(person, "name", { // 由於writable為true,所以可以修改value value: 'Lucy'}) console.log(person.name) // Lucy Object.defineProperty(person, "name", { // writable可進行true -> false的單向修改 writable: false}) Object.defineProperty(person, "name", { // throw error value: 'Lee'}) Object.defineProperty(person, "name", { // throw error,此時writable不可以false -> true writable: true})
總結一下configurable:當configurable設為false時,
1、不可以透過delete去刪除該屬性從而重新定義屬性;
2、不可以轉化為訪問器屬性;
3、configurable和enumerable不可被修改;
4、writable可單向修改為false,但不可以由false改為true;
5、value是否可修改根據writable而定。
當configurable為false時,用delete刪除該屬性,在非嚴格模式下,不會報錯,但操作被忽略,在嚴格模式下會報錯;其他不可被修改的特性修改時會報錯。
Enumerable
enumerable表示物件屬性是否可以在for...in和Object.keys()中被列舉。
var person = {}; Object.defineProperty(person, "a", { value : 1, enumerable:true }); Object.defineProperty(person, "b", { value : 2, enumerable:false }); Object.defineProperty(person, "c", { value : 3 }); // enumerable defaults to falseperson.d = 4; // 如果使用直接賦值的方式建立物件的屬性,則這個屬性的enumerable預設為truefor (var i in person) { console.log(i); } // 'a' 和 'd' Object.keys(person); // ["a", "d"]
訪問器屬性
訪問器屬性包含四個屬性描述符:
[[Configurable]] : 表示能否透過delete刪除屬性從而重新定義屬性,能否修改屬性特性,能否把屬性修改為資料屬性。直接在物件上定義的屬性,預設為true。
[[Enumerable]] : 表示能否透過for-in 迴圈訪問屬性。直接在物件上定義的屬性,預設為true。
[[Get]] : 讀取屬性時呼叫的函式,預設為undefined。
[[Set]] : 寫入屬性時呼叫的函式,預設為undefined。
var person = { name: 'Nicy', _age: 21, year: 1997, _year: 1997, sayName: function() { console.log(this.name); } } Object.defineProperty(person, "age", { get: function() { return this._age; }, set: function(value) { this._age = value; // ... } })
用Object.defineProperty()定義的訪問器屬性,其configurable和enumerable預設為false。
資料屬性與訪問器屬性的相互轉換
Object.getOwnPropertyDescriptor 讀取屬性的特性
使用Object.getOwnPropertyDescriptor可以獲取到屬性的描述符:
Object.getOwnPropertyDescriptor(obj, prop)
obj:屬性所在的物件;
prop:要訪問的屬性名。
資料屬性 -> 訪問器屬性
屬性的特性只能是訪問器描述符和資料描述符中的一種,給已有的資料屬性加get或set轉換為訪問器屬性時,其屬性的value、writable就會被廢棄。
如下程式碼,將物件原有的資料屬性year轉換為訪問器屬性:
*注:在訪問器屬性的get和set中,不可以使用this訪問屬性本身,否則會無限遞迴而導致記憶體洩漏。
// 設定get和set其中任意一個即可轉換為訪問器屬性Object.defineProperty(person, "year", { get: function() {// return this,year; // error return this._year; }, set: function(value) {// this.year = value; // error this._year= value; } })var descriptor = Object.getOwnPropertyDescriptor(person, 'year'); console.log(descriptor); // {get: ƒ, set: ƒ, enumerable: true, configurable: true}
在原有的資料屬性year中,使用Object.defineProperty()為屬性設定get 或 set,都可以將其轉換為訪問器屬性。
訪問器屬性 -> 資料屬性
將訪問器屬性轉換為資料屬性,只需要給現有訪問器屬性設定value或writable這兩個屬性描述符中的任意一個即可,其原有的get和set就會被廢棄,從而轉換為資料屬性。
上面為person定義的訪問器屬性age,透過Object.defineProperty()只設定了get和set,所以configurable預設為false,不可以將其轉換為資料屬性。可以在訪問器屬性和資料屬性間相互轉化的屬性其configurable特性值必須為true。
如下程式碼,我們為person新定義一個訪問器屬性job,將其configurable設定為true ,並將其轉換為資料屬性:
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}
資料描述符value、writable 和訪問器描述符get、set不能同時設定,否則會報錯。
Object.defineProperties()
透過Object.defineProperties()可以一次性為物件定義多個屬性。
var person = {}; Object.defineProperties(person, { name: { value: 'Nicy', writable: true }, _age: { value: 21, enumerable: true, writable: true, configurable: true }, age: { get: function() { return this._age; }, set: function(value) { this._age = value; } } });
原文出處:https://www.cnblogs.com/shiningly/p/9482283.html
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/200/viewspace-2812294/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- JavaScript物件的資料屬性與訪問器屬性JavaScript物件
- JavaScript訪問物件的屬性和方法JavaScript物件
- 理解 JavaScript 物件的屬性JavaScript物件
- javascript 物件屬性的get set訪問器寫法JavaScript物件
- c#屬性訪問器C#
- 深入理解屬性代理
- 深入理解Flex屬性Flex
- 深入理解display屬性
- js訪問物件屬性的2個方法JS物件
- 一、訪問物件屬性和方法的操作物件
- 深入理解JavaScript類與物件:揭秘類欄位和靜態屬性的妙用,js靜態屬性和例項屬性JavaScript物件JS
- JavaScript get set 訪問器屬性JavaScript
- c# tcbs屬性訪問器C#
- 原型鏈上的get與set訪問器屬性原型
- Python深入03 物件的屬性Python物件
- 深入理解CSS的display屬性CSS
- 深入理解 Getter和Setter 對物件的屬性監聽物件
- Python深入分享之物件的屬性Python物件
- javascript訪問物件屬性方式簡單介紹JavaScript物件
- css屬性與js中style物件的屬性對應表CSSJS物件
- 深入理解css中的margin屬性CSS
- javascript基礎(物件,物件屬性,屬性基本和引用資料型別,字面量建立物件,垃圾回收,屬性的列舉)(十三)JavaScript物件資料型別
- outerDocument訪問外部屬性方法
- 使用屬性而不是可訪問的資料成員
- 理解物件以及物件的屬性、方法、事件 (轉)物件事件
- 教你如何直接訪問php例項物件的private屬性PHP物件
- GObject的物件屬性GoObject物件
- Object物件的屬性Object物件
- 深入理解Vue 3:計算屬性與偵聽器的藝術Vue
- 深入理解 Python 的屬性查詢Python
- javascript原型物件的屬性不能夠覆蓋物件自有屬性JavaScript原型物件
- js物件屬性JS物件
- 深入理解 CSS 屬性值語法CSS
- Python 中的屬性訪問與描述符Python
- CAD屬性編輯操作——物件屬性教程物件
- python物件屬性管理(2):property管理屬性Python物件
- 屬性動畫與差值器動畫
- Python 快速教程(深入篇03):物件的屬性Python物件