Day21 | 物件的方法介紹-針對物件本身屬性操作的方法

❒ 屬性特徵

有很多原型是無法透過 chrome console 查看它的特徵,下方會依序介紹物件屬性比較特別的特徵,這些特徵也可以運用於框架間作出特別的效果。

調整物件本身屬性特徵( 參數 ) 的方法

  • Object.defineProperty:一次調整一個屬性。
  • Object.defineProperties:一次調整多個屬性。

definePropertydefineProperties 可調整的屬性特徵 ( 參數 )

  1. value:屬性本身的值,預設會為原來的值。
  2. writable:可否寫入,預設為 true。
  3. configurable:可否被刪除,預設為 true。
  4. enumerable:可否被列舉,預設為 true。

❒ Object.defineProperty ( 一次設定一個屬性 )

結構:Object.defineProperty(物件, 屬性, 參數);

1
2
3
4
5
6
7
// 參數可以只帶入要設定的即可
Object.defineProperty(物件, 屬性, {
value: , // 預設會為原來的值
writable: , // 預設為 true
configurable: , // 預設為 true
enumerable: , // 預設為 true
})
  • 屬性 依字串形式帶入。
  • 參數defineProperty 可以調整的屬性特徵( 參數 ),分別有:
    1. 屬性的值 value:可以去讀取或寫入這個值。
    2. 可否寫入 writable:一般來說值都可以被寫入,但可以使用 defineProperty 去限制屬性跟值是否可以被寫入。
    3. 可否被刪除 configurable:可設定此屬性是否可被刪除。
    4. 可否被列舉 enumerable:當不知道物件內有哪些屬性,可使用 for (變數 in 物件) {} 方法一一讀出物件內的屬性,一般來說這些屬性都可被讀出,可否被列舉意思為可限制哪些屬性是不可被列舉,當使用 for in 就不會讀到禁止被列舉的一些屬性。
  • Object.defineProperty 只能做到淺層保護,當屬性為物件時 defineProperty 只能對當下屬性做限制,不能對物件裡面的屬性做限制。可參考下方「 Object.defineProperty 其他使用方式 - 範例 2 」。

範例 1

1
2
3
4
5
6
7
8
9
10
11
12
var person = {
a: 1,
b: 2,
c: 3
}
console.log(person);
Object.defineProperty(person, 'a', {
value: 4,
writable: true,
configurable: true,
enumerable: true,
})

writable: false 屬性無法被寫入

  • person 中的 a 屬性就無法被寫入其他值。CodePen 範例
    • 但因為是靜默的錯誤,所以並不會跳出錯誤訊息。

configurable: true 屬性無法被刪除

  • 範例中可見 b 屬性設定了 configurable: true, ,使用 delete person.b; 是無法被刪除的。 CodePen 範例
    • 但因為是靜默的錯誤,所以並不會跳出錯誤訊息。

enumerable: false 屬性無法被列舉

  • 白話來說就是被設定的屬性當要一一列出時,是不會被顯示出來的。
  • 範例中 c 屬性被設定無法被列舉,所以當使用 for (變數 in 物件) {} 把物件屬性一一列出時,屬性 c 就不會出現。CodePen 範例
    • for (var key in person) {} 此方式會把 person 屬性帶到 key 上。

❒ Object.defineProperty 其他使用方式

範例 1. 新增物件屬性

1
2
3
4
5
6
7
8
9
10
11
12
13
var person = {
a: 1,
b: 2,
c: 3
}

Object.defineProperty(person, 'd', {
value: 4,
writable: true, //可否寫入
configurable:true, //可否刪除
enumerable: true, //可否列舉
})
console.log(person);
  • 屬性中使用物件內沒有的屬性,並於參數 value 加入值,可直接把新的屬性與屬性值加入物件中。

範例 2. Object.defineProperty 只能做到淺層保護

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var person = {
a: 1,
b: 2,
c: 3
}

Object.defineProperty(person, 'd', {
value: {},
writable: false,
})
person.d.dOne = 'D1';
person.d.dTwo = 'D2';

console.log(person);
  • Object.defineProperty 只能做到淺層保護,當屬性為物件時 defineProperty 只能對當下屬性做限制,不能對物件裡面的屬性做限制。

  • 範例中新增 d 屬性,屬性值為空物件,並設定不能寫入。console.log(person); 查看 d 為淺色,writable: false 在 d 屬性上有效。
    截圖

  • 在 d 的物件裡面新增屬性 dOne dTwoconsole.log(person); 查看 d 物件裡面的屬性為深色,writable: false 在 d 屬性裡面的物件是無效的。
    截圖

❒ Object.defineProperties ( 一次設定多個屬性 )

結構:Object.defineProperty(物件, {屬性們加上特徵});

1
2
3
4
5
6
7
8
9
10
11
12
Object.defineProperties(物件, {
屬性1: {
// --- 調整屬性的特徵
value: , // 預設會為原來的值
writable: , // 預設為 true
configurable: , // 預設為 true
enumerable: , // 預設為 true
},
屬性2: {
// 承上
}
})

範例1. 以調整屬性 a 與 b 的屬性值為例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var person = {
a: 1,
b: 2,
c: 3
}

Object.defineProperties(person, {
a: {
value: 5,
},
b: {
value: 7
}
})
console.log(person);

參考資訊

  • JavaScript 核心篇