welcome to Cheeto's blog

0%

JavaScript核心篇:物件擴充的修改與調整

物件擴充的修改與調整

這個章節一共會教三個物件方法:

  • preventExtensions - 防止擴充
  • seal - 封裝
  • Freeze - 凍結

preventExtensions - 防止擴充

preventExtensions用意是無法新增屬性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
var person = {
a: 1,
b: 2,
c: {}
}

Object.preventExtensions(person);
console.log('是否可被擴充', Object.isExtensible(person));
console.log('person a 的屬性特徵', Object.getOwnPropertyDescriptor(person, 'a'));

// 調整屬性
person.a = 'a';

// 新增屬性
person.d = 'd'; // 無效,因為防止擴充無法新增屬性

// 巢狀屬性調整
person.c.a = 'ca'; // 有效,因為防止擴充只能限制第一層

// 調整特徵
Object.defineProperty(person, 'a', {
configurable: false
});

// 刪除
delete person.b;

// 結果
console.log('person 物件', person);
console.log('person a 屬性特徵(嘗試修改後)', Object.getOwnPropertyDescriptor(person, 'a'));

物件擴充的修改與調整-1

我們可以看到 preventExtensions 主要的功能就是防止擴充,但是它的作用只能在指定物件的第一層屬性。因為物件是傳址的,所以只能對當下的屬性作動。

所以我們去刪除屬性、調整屬性都是被允許的。

seal - 封裝

seal : 讓指定物件的屬性無法新增、刪除,也無法重新配置特徵,但是可以調整屬性值。

  • 預設會讓物件加上 preventExtensions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
var person = {
a: 1,
b: 2,
c: {}
}

Object.seal(person);
console.log('是否可被擴充', Object.isExtensible(person));
console.log('是否被 封裝 ', Object.isSealed(person));
console.log('person a 的屬性特徵', Object.getOwnPropertyDescriptor(person, 'a'));

// 調整屬性
person.a = 'a'; // 有效,seal可以調整屬性值

// 新增屬性
person.d = 'd'; // 無效,seal 無法新增、刪除屬性

// 巢狀屬性調整
person.c.a = 'ca'; // 有效,因為 seal 只能限制第一層

// 調整特徵
Object.defineProperty(person, 'a', {
writable: false // 無效,seal 無法重新配置特徵
});

// 刪除
delete person.b; // 無效, seal 無法新增、刪除屬性

// 結果
console.log('person 物件', person);
console.log('person a 屬性特徵(嘗試修改後)', Object.getOwnPropertyDescriptor(person, 'a'));

物件擴充的修改與調整-2

可以看到seal不能被新增、刪除屬性,也無法重新配置特徵,但是可以被調整屬性值。

sealpreventExtensions 一樣只能限制到第一層的屬性。主要是因為物件是傳址的,所以只能對當下的屬性作動。

freeze

  • 物件會加上 seal,且無法調整值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
var person = {
a: 1,
b: 2,
c: {}
}

Object.freeze(person);
console.log('是否可被擴充', Object.isExtensible(person));
console.log('是否被 封裝 ', Object.isSealed(person));
console.log('是否被 凍結 ', Object.isFrozen(person));
console.log('person a 的屬性特徵', Object.getOwnPropertyDescriptor(person, 'a'));

// 調整屬性
person.a = 'a'; // 無效, freeze 無法調整值

// 新增屬性
person.d = 'd'; // 無效,freeze 無法新增、刪除屬性

// 巢狀屬性調整
person.c.a = 'ca'; // 有效,因為 freeze 只能限制第一層

// 刪除
delete person.b; // 無效, freeze 無法新增、刪除屬性

// 結果
console.log('person 物件', person);
console.log('person a 屬性特徵(嘗試修改後)', Object.getOwnPropertyDescriptor(person, 'a'));

物件擴充的修改與調整-3

freezeseal 的所有功能,但是它又多了一個不能調整值的功能。

還有另外一點,它在調整屬性特徵時 console.log 會跳錯。