【JS】《你不知道的JavaScript》 之 物件
阿新 • • 發佈:2018-11-20
簡單基本型別(string、boolean、number、null、undefined)本身並不是物件,但是typeof null時會返回字串‘object’。但實際上,null本身是基本型別。
原理是這樣的。不同的物件在底層都表示二進位制,在js中二進位制前三位都為0的話會被判斷為object,null的二進位制表示全部為0,自然前三位也是0.所以執行typeof時會返回‘object’。
陣列
陣列也是物件,所以雖然每個下標都是整數,仍可以給陣列新增屬性
var myArr = ['foo', 42, 'bar'] myArr.baz = 'baz' myArr.length // 3 myArr.baz // 'baz'
雖然添加了命名屬性,陣列的length值並未發生變化。
如果試圖向陣列新增一個屬性,但是屬性名‘看起來’像一個數字,那它會變成一個數值下標(因此會修改陣列的內容而不是新增一個屬性)
var myArr = ['foo', 42, 'bar']
myArr['3'] = 'baz'
myArr.length // 4
myArr[3] // 'baz'
屬性描述符
var myObj = {a:2} Object.getOwnPropertyDescriptor(myObj, 'a') // {value: 2, writable: true, enumerable: true, configurable: true}
這個普通的物件屬性對應的屬性描述符不僅僅是一個2.它還包含另外三個特性:writable、enumerable和configurable。
在建立普通屬性時屬性描述符會使用預設值,可以使用Object.defineProperty()來新增一個新屬性或者修改一個已有屬性(如果是configurable)。
var myObj = {} Object.defineProperty(myObj, 'a', { value: 3, configurable: true, enumerable: true, writable: true }) myObj.a // 2
除了defineProperty外還有defineProperties方法,差別如下:
Object.defineProperty(obj, prop, descriptor)
Object.defineProperties(obj, props)
- writable決定是否可以修改屬性的值
- configurable決定屬性是否可配置,只要屬性是可配置的,就可以使用defineProperty()方法來修改屬性描述符(把configurable修改為false是單向操作,無法撤銷);configurable: false 還會禁止刪除這個屬性
- enumerable決定的是該屬性是否會出現在物件的屬性列舉中。
不變性
- writable: false 和 configurable: false 就可以建立一個真正的常量屬性。
- 若想禁止一個物件新增新屬性並且保留已有屬性,可以使用Object.preventExtensions()。
- Object.seal()會建立一個‘密封’的物件,這個方法實際上會在一個現有物件上呼叫Object.preventExtensions()並把所有現有屬性標記為configurable: false。
- Object.freeze()會建立一個凍結物件,這個方法實際上會在一個現有物件上呼叫Object.seal()並把所有‘資料訪問’屬性標記為writable: false。
存在性
- in 會檢查物件及其原型鏈
- hasOwnProperty 只會檢查物件
- propertyIsEnumerable會檢查物件 並且 滿足enumerable: true
- Object.keys()會返回一個數組,包含所有可列舉屬性
- Object.getOwnPropertyNames()會返回一個數組,包含所有屬性,無論他們是否可列舉