物件屬性特徵
透過Oject.defineProperty
來定義物件的屬性,且可以調整這些屬性的特徵。
那屬性的特徵有哪些呢?
1.值 2.可否寫入 3.可否被刪除 4. 可否被列舉
那可否被列舉是什麼屬性呢?
就是說當我們想利用for
來遍歷某個物件內的所有屬性時,
若有個屬性是不可被列舉的話,則它就不會被遍歷到。
Oject.defineProperty 用法
Oject.defineProperty(物件, 屬性, 用法)
1 | var person = { |
另外,writable
是可否被重新寫入configurable
是可否被刪除enumerable
是可否被列舉
Oject.defineProperty 淺層保護
如果,我們今天對person這個物件新增的子物件d,並將它的writable
設為false
。
1 | Object.defineProperty(person, 'd', { |
因為,在JS中的物件是傳參考的特性,所以,更動物件是代表要轉換它原本所指向的物件位址,
那不可寫入的話,就代表我們不對該物件做傳換到另外一個位址的動作。
所以,你會發現d這個子物件還是維持原本的空物件狀態,
那如果我們對d新增屬性呢?
1 | Oject.defineProperty(person, 'd', { |
你會發現d確實新增了a屬性,而且它的值是6,而這個就是Oject.defineProperty
淺層保護的體現囉。
Object.defineProperties 插入多個屬性
1 | var person = { |
物件屬性不可寫入?物件擴充的修改與調整
本小節會介紹preventExtentions
, seal
, freeze
這三個方法。
中文分別代表: 防止擴充、封裝、凍結
Object.preventExtentions(物件)
這個方法的用意,就是不讓指定物件擴充新的屬性。
但是,它是無法防止該物件的巢狀屬性,擴充新的屬性。
1 | var person = { |
Object.seal(物件)
1.
讓指定物件屬性無法新增刪除,也無法重新配置特徵,但是,可以調整目前屬性值
當你使用Object.seal
時,程式會自動幫這個指定的物件加上preventExtentions
的特性。
即
1 | Object.seal(person) |
你可以看到我們沒有特別為person物件加上Object.preventExtensions,但是,它就又不能被擴充的特性。
這就是Object.seal
原本就具備的屬性。
2.Objec.seal
是不允許指定物件新增屬性的。
3.
有關於Object.seal
指定物件的巢狀屬性部分,他們的value還是可以被更改,但是,他們的屬性特徵是不能被修改的,
也就是不能修改這些巢狀屬性原本的writable
, configurable
, enumerable
的設定。
4.
但是,指定物件的巢狀屬性還是可以新增他們自己的屬性的。
Object.freeze(物件)
1.
指定物件會自動加上seal
特性,且無法調整值
2.Object.freeze
是不允許指定物件新增屬性的。
3.
有關於Object.freeze
指定物件的巢狀屬性部分,他們的value是不可以被更改,但是,他們的屬性特徵是不能被修改的,
也就是不能修改這些巢狀屬性原本的writable
, configurable
, enumerable
的設定。
4.
但是,指定物件的巢狀屬性還是可以新增他們自己的屬性的。
以上這三種方法,都是針對指定物件本身的操作,跟上一小節的Object.defineProperty
是針對物件內的屬性做操作是不太一樣的喔。
屬性列舉與原型的關係
這邊要講的是我們自訂的原型 和 原生的原型 有些許不同。
1 | function Person () {} |
以上你可以看到,key除了會引出ming自己的a屬性之外,也會印出Person的name屬性。
這個原因是因為,我們自訂的原型的屬性的enumerable
為true
,所以,它會在for
遍歷的時候,被印出來。
而原生的原型像是Object
的toString
屬性的enumerable
為false
,所以,不會在for
遍歷的時候被印出來。
如果我們不希望自訂的原型的屬性,在該子物件執行for
遍歷的時候被印出來的話,
我們就要利用Object.defineProperties
將該原型中的屬性的enumerable
設為false
。
1 | function Person () {} |
經過以上的處理,就不會將自訂原型的屬性name印出來囉。
Getter 與 Setter,賦值運算不使用函式
setter
: 存值的方法getter
: 取得特定值的方法
setter
1 | var wallet = { |
你可以看到,我們新增了一個setter
的屬性叫save,可以改變total的屬性值。
但這邊要特別注意的是,呼叫setter
的方式並不像我們一般在呼叫函式那樣子喔,
而是直接賦值給它,而這個賦值的內容,就是我們要傳入setter
的參數。
getter
1 | var wallet = { |
那這邊要注意的是,getter
是不用傳入參數的,畢竟它只是要取得數值的功能而已。
利用Object.defineProperty 來設置setter和getter
1 | var wallet = { |
經過Object.defineProperty
所設定的setter
和getter
,它們的屬性特徵configurable
和 enumerable
都是false
,若你按照原本直接在物件實字的內容裡面直接設定setter
和getter
的話,
它們的屬性特徵configurable
和 enumerable
就都是true
。
而如果像要改變這種狀況的話,就直接在Object.defineProperty
裡面,直接將屬性特徵configurable
和 enumerable
設成true
就可以了。
課程提供的getter的使用範例
1 | var a = [1, 2, 3] |
我們直接對Array
的原型新增一個叫latest的getter
,接著,所有的陣列都因為原型練的關係
都擁有latest這個getter
,可取得陣列的最後一個元素值。