JavaScript中對(duì)象屬性描述符的使用詳解
屬性描述符是 ECMAScript 5 新增的語法,它其實(shí)就是一個(gè)內(nèi)部對(duì)象,用來描述對(duì)象的屬性的特性。
屬性描述符的結(jié)構(gòu)
在 JavaScript 中,對(duì)象的屬性描述符用于描述和定義對(duì)象屬性的特性。以下是常見的屬性描述符及其作用:
configurable:表示屬性是否可以被刪除或修改特性。如果設(shè)置為 false,則不能刪除或修改該屬性的特性。默認(rèn)為 true。
enumerable:表示屬性是否可以通過 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)訪問該屬性時(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 讀寫屬性值的基本用法。
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 說明修改失敗
在正常模式下,如果 writable 為 false,重寫屬性值不會(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)語法或中括號(hào)語法訪問屬性的 value 外,還可以使用訪問器,包括 set 和 get 兩個(gè)函數(shù)。
其中,set( ) 函數(shù)可以設(shè)置 value 屬性值,而 get( ) 函數(shù)可以讀取 value 屬性值。
借助訪問器,可以為屬性的 value 設(shè)計(jì)高級(jí)功能,如禁用部分特性、設(shè)計(jì)訪問條件、利用內(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 : { //訪問器屬性
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)寫方法。針對(duì)示例 1,通過以下方式可以快速定義屬性。
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ì)象,無法直接讀寫,可以通過下面幾個(gè)函數(shù)進(jìn)行操作。
Object.getOwnPropertyDescriptor( ):可以讀出指定對(duì)象私有屬性的屬性描述符。
Object.defineProperty( ):通過定義屬性描述符來定義或修改一個(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: { //訪問器屬性
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; //過濾掉繼承屬性
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 種方法,用來精確控制一個(gè)對(duì)象的讀寫狀態(tài),防止對(duì)象被改變。
- Object.preventExtensions:阻止為對(duì)象添加新的屬性。
- Object.seal:阻止為對(duì)象添加新的屬性,同時(shí)也無法刪除舊屬性。等價(jià)于屬性描述符的 configurable 屬性設(shè)為 false。注意,該方法不影響修改某個(gè)屬性的值。
- Object.freeze:阻止為一個(gè)對(duì)象添加新屬性、刪除舊屬性、修改屬性值。
同時(shí)提供了 3 個(gè)對(duì)應(yīng)的輔助檢查函數(shù),簡(jiǎn)單說明如下:
- 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é)
這些描述符可以通過 Object.defineProperty() 方法來定義或修改對(duì)象的屬性特性。通過使用這些描述符,我們可以靈活地控制和定義對(duì)象的屬性行為,例如限制某些屬性只讀、隱藏某些不需要枚舉的屬性等。
總的來說,對(duì)象的屬性描述符提供了對(duì)對(duì)象屬性行為進(jìn)行詳細(xì)控制和定義的能力,包括可配置性、可枚舉性、可寫性、獲取和設(shè)置方法等。這使得我們能夠更好地管理和操作對(duì)象中的各個(gè)屬性。
到此這篇關(guān)于JavaScript中對(duì)象屬性描述符的使用詳解的文章就介紹到這了,更多相關(guān)JavaScript屬性描述符內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JS?TypeScript的Map對(duì)象及聯(lián)合類型實(shí)戰(zhàn)
這篇文章主要介紹了JS?TypeScript的Map對(duì)象及聯(lián)合類型實(shí)戰(zhàn),文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-08-08
JavaScript實(shí)現(xiàn)身份證驗(yàn)證代碼實(shí)例
這篇文章主要介紹了JavaScript實(shí)現(xiàn)身法證驗(yàn)證代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08
js+canvas實(shí)現(xiàn)轉(zhuǎn)盤效果(兩個(gè)版本)
這篇文章主要為大家詳細(xì)介紹了兩個(gè)版本的js+canvas實(shí)現(xiàn)轉(zhuǎn)盤效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-09-09
基于JavaScript實(shí)現(xiàn)可搜索的表格
在Web開發(fā)中,數(shù)據(jù)表格是常見的數(shù)據(jù)展示形式,這篇文章主要為大家詳細(xì)介紹了如何使用JavaScript來實(shí)現(xiàn)這個(gè)功能,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-01-01
Bootstrap基本插件學(xué)習(xí)筆記之標(biāo)簽切換(17)
這篇文章主要為大家詳細(xì)介紹了Bootstrap基本插件學(xué)習(xí)筆記之標(biāo)簽切換的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12

