JavaScript中對(duì)象屬性描述符的使用詳解
屬性描述符是 ECMAScript 5 新增的語(yǔ)法,它其實(shí)就是一個(gè)內(nèi)部對(duì)象,用來(lái)描述對(duì)象的屬性的特性。
屬性描述符的結(jié)構(gòu)
在 JavaScript 中,對(duì)象的屬性描述符用于描述和定義對(duì)象屬性的特性。以下是常見(jiàn)的屬性描述符及其作用:
configurable:表示屬性是否可以被刪除或修改特性。如果設(shè)置為 false,則不能刪除或修改該屬性的特性。默認(rèn)為 true。
enumerable:表示屬性是否可以通過(guò) for...in 循環(huán)或 Object.keys() 方法進(jìn)行枚舉。如果設(shè)置為 false,則該屬性不會(huì)出現(xiàn)在枚舉中。默認(rèn)為 true。
value:表示屬性的值??梢允侨魏斡行У?JavaScript 值。
writable:表示屬性是否可以被賦值運(yùn)算符修改。如果設(shè)置為 false,則該屬性的值不能被修改。默認(rèn)為 true。
get:一個(gè)函數(shù),用于獲取屬性的值。當(dāng)訪問(wèn)該屬性時(shí),會(huì)調(diào)用該函數(shù)并返回其返回值。
set:一個(gè)函數(shù),用于設(shè)置屬性的值。當(dāng)給該屬性賦值時(shí),會(huì)調(diào)用該函數(shù)并傳入新值作為參數(shù)。
注意這幾個(gè)屬性不是都可以一起設(shè)置。get 和 set 以及 value 和 writable 這兩組是互斥的,設(shè)置了 get 和 set 就不能設(shè)置 value 和 writable,反之設(shè)置了 value 和 writable 也就不可以設(shè)置 get 和 set。
使用示例
示例 1
下面示例演示了使用 value 讀寫(xiě)屬性值的基本用法。
var obj = {} //定義空對(duì)象 Object.defineProperty(obj, 'x', {value : 100}) //添加屬性x,值為100 console.log(Object.getOwnPropertyDescriptor(obj, 'x').value) //返回100
示例 2
下面示例演示了使用 writable 屬性禁止修改屬性 x。
var obj = {}; Object.defineProperty(obj, 'x', { value : 1, // 設(shè)置屬性默認(rèn)值為1 writable : false // 禁止修改屬性值 }); obj.x = 2; //修改屬性x的值 console.log(obj.x) // 1 說(shuō)明修改失敗
在正常模式下,如果 writable 為 false,重寫(xiě)屬性值不會(huì)報(bào)錯(cuò),但是操作失敗,而在嚴(yán)格模式下則會(huì)拋出異常。
示例 3
configurable 可以禁止修改屬性描述符,當(dāng)其值為 false 時(shí),value、writable、enumerable 和 configurable 禁止修改,同時(shí)禁止刪除屬性。
在下面示例中,當(dāng)設(shè)置屬性 x 禁止修改配置后,下面操作都是不允許的,其中 obj.x=5; 若操作失敗,則后面 4 個(gè)操作方法都將拋出異常。
var obj = Object.defineProperty({}, 'x', { configurable : false // 禁止配置 }) obj.x = 5 // 試圖修改其值 console.log(obj.x); // 修改失敗,返回undefined Object.defineProperty(obj, 'x', {value : 2}) // 拋出異常 Object.defineProperty(obj, 'x', {writable: true}) // 拋出異常 Object.defineProperty(obj, 'x', {enumerable: true}) // 拋出異常 Object.defineProperty(obj, 'x', {configurable: true}) // 拋出異常
當(dāng) configurable 為 false 時(shí),如果把 writable=true 改為 false 是允許的。只要 writable 或 configurable 有一個(gè)為 true,則 value 也允許修改。
get 和 set 函數(shù)
除了使用點(diǎn)語(yǔ)法或中括號(hào)語(yǔ)法訪問(wèn)屬性的 value 外,還可以使用訪問(wèn)器,包括 set 和 get 兩個(gè)函數(shù)。
其中,set( ) 函數(shù)可以設(shè)置 value 屬性值,而 get( ) 函數(shù)可以讀取 value 屬性值。
借助訪問(wèn)器,可以為屬性的 value 設(shè)計(jì)高級(jí)功能,如禁用部分特性、設(shè)計(jì)訪問(wèn)條件、利用內(nèi)部變量或?qū)傩赃M(jìn)行數(shù)據(jù)處理等。
示例 1
下面示例設(shè)計(jì)對(duì)象 obj 的 x 屬性值必須為數(shù)字。為屬性 x 定義了 get 和 set 特性,obj.x 取值時(shí),就會(huì)調(diào)用 get;賦值時(shí),就會(huì)調(diào)用 set。
var obj = Object.create(Object.prototype, { _x : { //數(shù)據(jù)屬性 value : 1, //初始值 writable : true }, x : { //訪問(wèn)器屬性 get : function () { //getter return this._x; //返回_x屬性值 }, set : function (value) { //setter if (typeof value != "number"){ throw new Error('請(qǐng)輸入數(shù)字'); } this._x = value; //賦值 } } }); console.log(obj.x); //1 obj.x = "2"; //拋出異常
示例 2
JavaScript 也支持一種簡(jiǎn)寫(xiě)方法。針對(duì)示例 1,通過(guò)以下方式可以快速定義屬性。
var obj = { _x : 1, // 定義 _x 屬性 get x() { return this._x }, //定義 x 屬性的 getter set x(value) { //定義 x 屬性的 setter if (typeof value != "number"){ throw new Error('請(qǐng)輸入數(shù)字'); } this._x = value; // 賦值 } }; console.log(obj.x); //1 obj.x = 2; console.log(obj.x); //2
取值函數(shù) get( ) 不能接收參數(shù),存值函數(shù) set( ) 只能接收一個(gè)參數(shù),用于設(shè)置屬性的值。
操作屬性描述符
屬性描述符是一個(gè)內(nèi)部對(duì)象,無(wú)法直接讀寫(xiě),可以通過(guò)下面幾個(gè)函數(shù)進(jìn)行操作。
Object.getOwnPropertyDescriptor( ):可以讀出指定對(duì)象私有屬性的屬性描述符。
Object.defineProperty( ):通過(guò)定義屬性描述符來(lái)定義或修改一個(gè)屬性,然后返回修改后的描述符。
Object.defineProperties( ):可以同時(shí)定義多個(gè)屬性描述符。
Object.getOwnPropertyNames( ):獲取對(duì)象的所有私有屬性。
Object.keys( ):獲取對(duì)象的所有本地可枚舉的屬性。
propertyIsEnumerable( ):對(duì)象實(shí)例方法,直接調(diào)用,判斷指定的屬性是否可枚舉。
示例 1
在下面示例中,定義 obj 的 x 屬性允許配置特性,然后使用 Object.getOwnPropertyDescriptor( ) 函數(shù)獲取對(duì)象 obj 的 x 屬性的屬性描述符。修改屬性描述符的 set 函數(shù),重設(shè)檢測(cè)條件,允許非數(shù)值型數(shù)字賦值。
var obj = Object.create(Object.prototype, { _x: { //數(shù)據(jù)屬性 value: 1, //初始值 writable: true }, x: { //訪問(wèn)器屬性 configurable: true, //允許修改配置 get: function () { //getter return this._x; //返回_x屬性值 }, set: function (value) { if (typeof value != "number") { throw new Error('請(qǐng)輸入數(shù)字'); } this._x = value; //賦值 } } }); var des = Object.getOwnPropertyDescriptor(obj, "x"); //獲取屬性x的屬性描述符 des.set = function (value) { //修改屬性x的屬性描述符set函數(shù) //允許非數(shù)值型的數(shù)字,也可以進(jìn)行賦值 if (typeof value != "number" && isNaN(value * 1)) { throw new Error('請(qǐng)輸入數(shù)字'); } this._x = value; } obj = Object.defineProperty(obj, "x", des); console.log(obj.x); //1 obj.x = "2"; //把一個(gè)給數(shù)值型數(shù)字賦值給屬性x console.log(obj.x); //2
示例 2
下面示例先定義一個(gè)擴(kuò)展函數(shù),使用它可以把一個(gè)對(duì)象包含的屬性以及豐富的信息復(fù)制給另一個(gè)對(duì)象。
【實(shí)現(xiàn)代碼】
function extend (toObj, fromObj) { //擴(kuò)展對(duì)象 for (var property in fromObj) { //遍歷對(duì)象屬性 if (!fromObj.hasOwnProperty(property)) continue; //過(guò)濾掉繼承屬性 Object.defineProperty( //復(fù)制完整的屬性信息 toObj, //目標(biāo)對(duì)象 property, //私有屬性 Object.getOwnPropertyDescriptor(fromObj, property) //獲取屬性描述符 ); } return toObj; //返回目標(biāo)對(duì)象 }
【應(yīng)用代碼】
var obj = {}; //新建對(duì)象 obj.x = 1; //定義對(duì)象屬性 extend(obj, { get y() { return 2} }) //定義讀取器對(duì)象 console.log(obj.y); //2
控制對(duì)象狀態(tài)
JavaScript 提供了 3 種方法,用來(lái)精確控制一個(gè)對(duì)象的讀寫(xiě)狀態(tài),防止對(duì)象被改變。
- Object.preventExtensions:阻止為對(duì)象添加新的屬性。
- Object.seal:阻止為對(duì)象添加新的屬性,同時(shí)也無(wú)法刪除舊屬性。等價(jià)于屬性描述符的 configurable 屬性設(shè)為 false。注意,該方法不影響修改某個(gè)屬性的值。
- Object.freeze:阻止為一個(gè)對(duì)象添加新屬性、刪除舊屬性、修改屬性值。
同時(shí)提供了 3 個(gè)對(duì)應(yīng)的輔助檢查函數(shù),簡(jiǎn)單說(shuō)明如下:
- Object.isExtensible:檢查一個(gè)對(duì)象是否允許添加新的屬性。
- Object.isSealed:檢查一個(gè)對(duì)象是否使用了 Object.seal 方法。
- Object.isFrozen:檢查一個(gè)對(duì)象是否使用了 Object.freeze 方法。
示例
下面代碼分別使用 Object.preventExtensions、Object.seal 和 Object.freeze 函數(shù)控制對(duì)象的狀態(tài),然后再使用 Object.isExtensible、Object.isSealed 和 Object.isFrozen 函數(shù)檢測(cè)對(duì)象的狀態(tài)。
var obj1 = {}; console.log(Object.isExtensible(obj1)); //true Object.preventExtensions(obj1); console.log(Object.isExtensible(obj1)); //false var obj2 = {}; console.log(Object.isSealed(obj2)); //true Object.seal(obj2); console.log(Object.isSealed(obj2)); //false var obj3 = {}; console.log(Object.isFrozen(obj3)); //true Object.freeze(obj3); console.log(Object.isFrozen(obj3)); //false
總結(jié)
這些描述符可以通過(guò) Object.defineProperty() 方法來(lái)定義或修改對(duì)象的屬性特性。通過(guò)使用這些描述符,我們可以靈活地控制和定義對(duì)象的屬性行為,例如限制某些屬性只讀、隱藏某些不需要枚舉的屬性等。
總的來(lái)說(shuō),對(duì)象的屬性描述符提供了對(duì)對(duì)象屬性行為進(jìn)行詳細(xì)控制和定義的能力,包括可配置性、可枚舉性、可寫(xiě)性、獲取和設(shè)置方法等。這使得我們能夠更好地管理和操作對(duì)象中的各個(gè)屬性。
到此這篇關(guān)于JavaScript中對(duì)象屬性描述符的使用詳解的文章就介紹到這了,更多相關(guān)JavaScript屬性描述符內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JS簡(jiǎn)單測(cè)試循環(huán)運(yùn)行時(shí)間的方法
這篇文章主要介紹了JS簡(jiǎn)單測(cè)試循環(huán)運(yùn)行時(shí)間的方法,涉及針對(duì)javascript中for循環(huán)、for...in循環(huán)及foreach循環(huán)的相關(guān)使用方法及運(yùn)行時(shí)間測(cè)試,需要的朋友可以參考下2016-09-09也說(shuō)JavaScript中String類(lèi)的replace函數(shù)
最近讀了sharpxiajun的博文《javascript筆記--String類(lèi)replace函數(shù)的一些事》,感覺(jué)寫(xiě)的很好,很有幫助。2011-09-09JS簡(jiǎn)單生成兩個(gè)數(shù)字之間隨機(jī)數(shù)的方法
這篇文章主要介紹了JS簡(jiǎn)單生成兩個(gè)數(shù)字之間隨機(jī)數(shù)的方法,涉及javascript數(shù)值運(yùn)算的相關(guān)技巧,需要的朋友可以參考下2016-08-08JSON.parse處理非標(biāo)準(zhǔn)Json數(shù)據(jù)出錯(cuò)的解決
這篇文章主要介紹了JSON.parse處理非標(biāo)準(zhǔn)Json數(shù)據(jù)出錯(cuò)的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09javascript的動(dòng)態(tài)加載、緩存、更新以及復(fù)用(一)
在做OA、MIS、ERP等信息管理類(lèi)的項(xiàng)目,經(jīng)常會(huì)遇到引用很多js文件,這就需要用到動(dòng)態(tài)加載、緩存、更新以及復(fù)用等技術(shù),下面我們來(lái)討論下2014-06-06