此次咱們好好聊一聊對象這個東西,本次說的不是array
,也不是function
,而是object
對象是一種特殊的數據類型,這種數據類型還有其餘的不少叫法,好比「散列」,「散列表」,「字典」,「關聯數組」。javascript
對象按照建立者的角度,能夠分爲三類:內置對象
:是由javascript語言自己自定義的對象,大多數是一些預約好的構造函數類,好比Array
,Date
,Function
宿主對象
:是指javascript解釋器所嵌入的宿主環境定義的對象,好比HTMLElement就是宿主對象。自定義對象
:是指由開發者在代碼中所建立的對象。java
咱們知道對象的表達方式是:'屬性':'值'api
屬性按照來源不一樣,能夠分爲兩類:自有屬性
:是指直接在對象中定義的屬性。繼承屬性
:是指在對象原型鏈中的屬性。數組
與此同時,對象的屬性還具備一些特性:可寫
:表明是否能夠設置該對象所對應的該屬性的值。可枚舉
:表明是否能夠經過api枚舉出該屬性。可配置
:表明是否能夠刪除或修改該屬性。函數
記住上述概念,有助於咱們進行下一步的理解。this
建立對象有三種方式:
第一種:對象直接量spa
var o = {} var obj = { a: 1, 'b': 2, 'min title': 3 }
第二種:經過new建立對象code
var o = new Object()
第三種:Object.create()
該方法支持傳入兩個參數,第一個參數是對象的原型(就是所建立出的對象的_proto_
的指向),第二個參數是對屬性進一步的描述(該參數可選,參數內容會在後面詳解)對象
如下三種方式是等價的:blog
檢測對象原型的方法除了instanceof
以外,還有一個isPrototypeOf()
,咱們來看一下使用:
咱們首先再明確一個概念:
咱們常見的{a: 1}
中的a
叫作數據屬性
,除此以外還有一個叫作存取器屬性
,存取器屬性的值的讀取和設置,都是由getter和setter控制的。
var o = { p: 0, set q(value) { this.p = value }, get q() { return this.p+=100 } } o.q = 1 console.log(o.q) // => 101 console.log(o.q) // => 201
其中,對象中的函數定義沒有使用function
關鍵字,使用的而是get
和set關鍵字
處理能夠這樣定義存取器屬性,咱們還能夠利用其餘的方法定義存取器屬性
,就是咱們熟知的Object.defineProperty()
和Object.definePeoperties()
首先,咱們介紹一下Object.defineProperty()
定義數據屬性
的方式
var o = {} // 定義屬性 Object.defineProperty( o, 'x', { value: 1, writable: true, enumerable: true, configurable: true } ) // 修改屬性 Object.defineProperty( o, 'x', { value: 2, writable: false } )
這個函數共有三個參數:
第一個參數是,須要加屬性的對象。
第二個參數是,添加的屬性的名稱。
第三個參數是定義的配置項:
第一個配置就是這個屬性所對應的值。
剩餘三個配置就是對應到文章一開始所提到屬性三個特性可寫
,可枚舉
,可配置
。
這四個配置項都不是必須填寫。假如對於新建立的屬性,value不填,默認值就是undefined
,其餘配置項的缺省值是false
。假如對於修改已有的屬性來講,不填寫的配置項就不作修改。
咱們再看一下Object.defineProperty()
定義存取器屬性
的方式
其中,須要注意的是,在定義存取器屬性
時沒法定義,value
和writable
配置項,由於定義的get
和set
從某種意義上代替了前兩個配置項。
var o = {y: 1} Object.defineProperty( o, 'x', { set(value) { this.y = value }, get() { return this.y+=100 }, enumerable: true, configurable: true } )
Object.defineProperty
只能單個定義或修改對象屬性,Object.defineProperties
提供了批量解決的辦法,以下:
var o = {} Object.defineProperties( o, { x: { set(value) { this.y = value }, get() { return this.y+=100 }, enumerable: true, configurable: true }, y: { value: 1, writable: false, enumerable: true, configurable: true } } )
Object.defineProperty
和Object.defineProperties
對於屬性的修改是有規則和要求的,以下:
在這裏,咱們再看一下上面的Object.create
方法,Object.create
的第二個參數是和Object.defineProperties
第二個參數同樣的,缺省值一樣爲undefined
和false
沒有提供選項去配置屬性特性的方法,這些屬性默認都是true,例如:new
關鍵字和對象直接量的方式建立對象,以及最上面對象直接量的方式設置getter和setter
對象的擴展性是什麼,其實就是指對象可否添加新的屬性,默認狀況下全部的內置對象和自定義對象都是可擴展的。除非咱們人爲的改變它:
Object.preventExtesions()
能夠傳入一個參數,就是你要取消擴展功能的對象,操做後,這個對象會不能擴展(即不能添加新屬性),且不能恢復,操做隻影響該對象自己,不對其餘原型鏈操做產生影響。
咱們能夠利用Object.esExtensible()
判斷這個對象是否可擴展,傳入一個對象,返回布爾值。
Object.seal()
能夠將對象封閉,效果和上面的Object.preventExtesions()
同樣,增長的效果是將這個對象的自有屬性設置爲不可配置(即將configurable設爲false),一樣不能解封。
咱們能夠利用Object.isSealed()
來判斷這個對象是否封閉,傳入一個對象,返回布爾值。
Object.freeze()
能夠將對象冰凍,效果和上面的Object.seal()
同樣,增長的效果是將這個對象的自有屬性設置爲不可寫(即將writable設爲false),一樣不能解凍。Object.isFrozen()
能夠判斷這個對象是否冰凍。
根據屬性查詢值的方式咱們固然是衆所周知了,[]
和.
,固然他們也能夠設置和修改可寫性爲true的自有屬性值
var o = {} Object.defineProperties( o, { x: { value: 1, writable: true, enumerable: true, configurable: true }, y: { value: 1, writable: false, enumerable: true, configurable: true } } ) o.x // => 1 o['x'] = 5 o.x // => 5 o.y = 5 o.y // => 1
delete
能夠用戶刪除對象屬性,能刪除的屬性只是該對象的自有屬性
且屬性配置性爲true
的屬性
讓人感到意外的是,delete
只是斷開屬性和宿主對象的聯繫,而不會去操做屬性中的屬性。
檢測屬性共有三種方式,in
操做符,hasOwnProperty
和propertyIsEnumerable
in
能夠檢測對象的自有屬性
和繼承屬性
,不受屬性特性的影響
var o = {x: 1} 'x' in o // true 'y' in o // false 'toString' in o // true
hasOwnProperty
只能檢測對象的自有屬性
,不能檢測繼承屬性
,不受屬性特性的影響
var o = {x: 1} o.hasOwnProperty('x') // true o.hasOwnProperty('y') // false o.hasOwnProperty('toString') // false
propertyIsEnumerable
只能檢測自有屬性
,且要求這個屬性的可枚舉性爲true
首先第一個方法是for/in
,這個方法能夠枚舉出當前對象可枚舉(屬性枚舉性爲true)的自有屬性和繼承屬性
var o = Object.create({z: 1}) Object.defineProperties( o, { x: { value: 1, writable: true, enumerable: true, configurable: true }, y: { value: 1, writable: false, enumerable: false, configurable: true } } ) for (p in o) {console.log(p)} // => x, z
第二個方法是Object.keys()
,這個方法能夠枚舉出當前對象的可枚舉(屬性枚舉性爲true)的自有屬性
,返回值是一個數組
var o = Object.create({z: 1}) Object.defineProperties( o, { x: { value: 1, writable: true, enumerable: true, configurable: true }, y: { value: 1, writable: false, enumerable: false, configurable: true } } ) Object.keys(o) // => ['x']
第三個方法是Object.getOwnPropertyNames
,它能夠枚舉出當前對象全部的自有屬性(不受枚舉性影響)
Object.defineProperties( o, { x: { value: 1, writable: true, enumerable: true, configurable: true }, y: { value: 1, writable: false, enumerable: false, configurable: true } } ) Object.getOwnPropertyNames(o) // => ['x', 'y']
JSON.stringify()
和JSON.parse()