js對象可擴展性和屬性的四個特性(上)
一、前言
-
再次花時間回顧一下基礎,畢竟要想樓建的好,地基就要牢固,嘻嘻!
-
在開始之前需要具備對prototype、__proto__、constructor有一定得了解,可以看看我之前寫的一篇文章=>通道
-
之前的用戶管理系統已經差不多了,順便加了個socket聊天的,但是由於做java后台的哪個朋友節奏跟不上來,所以即時聊天的后台就是node+socket-io寫的,由於用戶列表也涉及比較多的用戶隱私問題,所以我設置了頁面權限和接口權限,然后下面開放的幾個賬號就只能看到幾個頁面而已,哈哈。=>通道
-
體驗賬號1:賬號:“123456”。密碼:“123456”
-
體驗賬號2:賬號:“123123”。密碼:“123123”
二、目錄
- 對象屬性的四個特性
- 對象的可擴展性
- 刪除屬性
- 檢測屬性
- 枚舉屬性
- 屬性的getter和setter
三、對象屬性的四個特性
1、定義
1.1、什么是數據屬性?
數據屬性就是我們平常看到的對象普通屬性。
數據屬性的特性為以下四種:
值(value)
可寫性(writable)
可枚舉性(enumerable)
可配置性(configurable)
1.2、什么是存儲器屬性?
存儲器屬性是由getter和setter定義的屬性
存儲器屬性特性為以下四種:
讀取(get)
寫入(set)
可枚舉性(enumerable)
可配置性(configurable)
2、方法
2.1、獲取某個對象特定屬性的屬性描述
Object.getOwnPropertyDescriptor()
const log = console.log;
//返回數據數據的描述
let aa = {
x: 1
};
log(Object.getOwnPropertyDescriptor(aa, 'x'))
//返回存儲器屬性的描述
let bb = {
get y() {
return 2;
},
}
log(Object.getOwnPropertyDescriptor(bb, 'y'))
//對於一個不存在的屬性或者繼承屬性返回undefined
log(Object.getOwnPropertyDescriptor({}, 'x'))
log(Object.getOwnPropertyDescriptor({}, 'toString'))
2.2、讓新建屬性具有某種特性
Object.defineProperty()
說明:
- defineProperty不能修改繼承屬性
- defineProperty不必包含所有四個屬性,對於已有的屬性來說,未指定的特性不做修改,只對指定特性進行修改。
- 對於新創建的屬性來說默認是false或者undefined。
- 當configurable設置為false,就不能再設置為true了,因為不可配置也不能配置自己
- 當configurable設置為true,writable設置為false時,是可以通過配置特性更改value值的
- 當configurable設置為false時,writable可以從true設置為false,當時不能從false設置為true
const log = console.log;
var aa = {
y: 22
};
//添加一個x屬性為不可寫、不可枚舉、可配置
Object.defineProperty(aa, 'x', {
value: 1,
writable: false,
enumerable: false,
configurable: true
})
log(aa.x);
aa.x = 2; //嘗試修改這個屬性會失敗,但是不會報錯,在嚴格模式下會報錯
log(aa.x)
for (let i in aa) {
//不可枚舉數據屬性x,但是y可以枚舉
console.log(i)
}
//因為這個x屬性依然是可以配置的,所以可以通過配置的方式對值進行修改
Object.defineProperty(aa, 'x', {
value: 3,
})
log(aa.x);
//將數據屬性設置為存儲器屬性
Object.defineProperty(aa, 'x', {
get: function() {
return 4;
},
})
log(aa.x)
2.3、同時修改多個屬性的特性
Object.defineProperties()
const log = console.log;
var aa = {};
Object.defineProperties(aa, {
x: {value: 1,writable: false,enumerable: true,configurable: false},
y: {value: 2,writable: false,enumerable: true,configurable: false},
z: {
get:function(){
return 3
},
enumerable: false,
configurable: false
}
})
for(let i in aa){
log(i,'---',aa[i])
}
log('z','---',aa.z)
四、對象的可擴展性
1、定義
1.1、什么是可擴展性?
對象可擴展性是指是否可以給該對象添加新的屬性
2、方法
2.1、將對象設置為不可擴展
Object.preventExtensions()
說明:
- 對象一旦設置不為不可擴展就不能轉換為可擴展了
- Object.preventExtensions只會影響對象本身的可擴展性,所以依然還是可以給對象原型添加屬性。
const log = console.log;
var aa = {};
Object.preventExtensions(aa);
aa.x = 1;
log(aa.x)
2.2、檢測對象是否是可擴展的
Object.isExtensible()
//在《javascript權威指南》第六版中6.8.3節介紹可擴展性的時候,將isExtensible寫為esExtensible了。
const log = console.log;
var aa = {};
var bb = {};
Object.preventExtensions(aa);
log(Object.isExtensible(aa))
log(Object.isExtensible(bb))
2.3、將對象封閉(sealed)
Object.seal()
說明:
- Object.seal不僅可以設置對象的可擴展性,還可以設置對象的所有自有屬性的可配置性
- 將對象設置為不可擴展並且不可配置,也就是說不能給這個對象添加新屬性,而且已有的屬性不能刪除或者配置。
- 不過這些屬性可寫特性依然是可以配置的
const log = console.log;
var aa = {
y: 2
};
Object.seal(aa);
aa.x = 1;
log(aa.x);
log(Object.getOwnPropertyDescriptor(aa, 'y'))
Object.defineProperty(aa, 'y', {
writable: false,
})
log(Object.getOwnPropertyDescriptor(aa, 'y'))
2.4、檢測對象是否被封閉
Object.isSealed()
const log = console.log;
var aa = {};
var bb = {};
Object.seal(aa);
log(Object.isSealed(aa));
log(Object.isSealed(bb))
2.5、將對象凍結(freeze)
Object.freeze()
說明:
- freeze不僅僅可以將對象設置為不可擴展和所有屬性為不可配置,並且會將所有對象屬性設置為只讀。
- 如果存取器屬性具有setter方法,則不會受到影響,仍然可以通過此方法給屬性賦值。
const log = console.log;
var aa = {
x: 1
};
Object.freeze(aa);
log(Object.getOwnPropertyDescriptor(aa, 'x'))
2.6、檢測對象是否配凍結
Object.isFreeze()
const log = console.log;
var aa = {};
var bb = {};
Object.freeze(aa);
log(Object.isFrozen(aa));
log(Object.isFrozen(bb));