內容有點兒多,將分爲兩篇內容與你們分享。有的地方確實難以理解,能夠多動手實現一下,看看效果。javascript
一直據說有這麼一句話,在JavaScript中,一切皆爲對象。 java
經本人慎重研究以後發現,此言的確不虛。(這不廢話麼,虛不虛的還用你說。)函數
今天斗膽跟你們一塊兒討論一下JavaScript
重的Object
。瞭解Object
背後的 -- 生活
性能
閱讀間隙,還得多注意休息喲~this
開始第一個小問題,看一下如何建立一個對象。建立對象有四(shi)種方式。如下幾種方式均可建立一個對象,只不過建立以後的表現稍有不一樣。具體表現爲原型和this
的指向問題。有興趣的讀者可點擊查看相關文章。在這裏咱們就不詳細介紹了。(偷個懶)prototype
注意點:對象
四種方式建立對象,除了原型和this
指針表現不一樣,構造函數指向也有不一樣。(此時說明的是不手動指定構造函數的狀況下)ip
function Object() {}
Object.create
建立的對象,構造函數爲入參origin
的構造函數class
方式建立,會將自己也做爲構造函數。const obj = {} // 構造函數爲 [Function: Object]
function Obj() {} const obj = new Obj() // 構造函數爲 [Function: origin]
const origin = {a: 1, b: 2} const target = Object.create(origin) // 構造函數爲 origin 的構造函數
class Origin {} const target = new Origin() // 構造函數 [Function: Origin]
注:
官方版
通俗版
key
屬性,使用 .
運算符 或 中括號const obj = { a: 1, b: 2, c: 3, d: function () {} } obj.a === obj['a']// 1 obj.b === obj['b'] // 2 obj.c === obj['c'] // 3 obj.d === obj['d'] // function (){}
kay
值,只能使用中括號方式const obj = { a1: 1, a2: 2, a3: 3, a4: function (){} } for(let i = 1;i < 5;i ++) { obj['a' + i] } // 1,2,3,function (){}
注意:
若是對象中不含有某個key
,獲取到的爲 undefined
例如:
const obj = {} obj.c() // TypeError: obj.c is not a function
因爲obj
中不含有c
這個方法,因此獲取到的是undefined
。此值不是函數,執行報錯
可修改成如下寫法
const obj = {} typeof obj.c === 'function' && obj.c()
這裏有的讀者可能會說這樣也能夠 obj.c && obj.c()
。這種寫法在下面這種狀況下依然會報錯
const obj = { c: 1 } obj.c()
因此,仍是要清楚的判斷咱們要獲取的key
是一個函數,才能執行。
在此段內容開始以前,先說一個小問題,如何判斷對象中是否含有某個key
值?
2.1
中的屬性獲取undefined
便可。undefined
,則會出現判斷失誤的狀況const obj = { c: undefined } console.log(obj.c === 'undefined') // 判斷爲true,可是obj中確實含有c這個key
in
key
// 包含某個key function A () { this.b = 1 } const a = new A() console.log('b' in a) // true
key
// 不包含某個key function A () { } const a = new A() console.log('b' in a) // false
key
,值爲 undefined
的狀況// 不包含某個key function A () { this.b = undefined } const a = new A() console.log('b' in a) // true
key
存在於原型鏈上function A () { } Object.prototype.b = 1 const a = new A() console.log('b' in a) // true
注意點:
缺點:in
方法沒法判斷當前key
是存在於對象自己仍是在原型鏈上。此狀況,咱們須要用到下面這種方法。
hasOwnProperty
查詢屬性是否存在於自身function A () {} Object.prototype.b = 1 const a = new A() console.log(a.hasOwnProperty('b')) // false
function A () { this.b = 1 } const a = new A() console.log(a.hasOwnProperty('b')) // true
undefined
function A () { this.b = undefined } const a = new A() console.log(a.hasOwnProperty('b')) // true
總結:
undefined
的狀況in
方法不能判斷屬性是在對象自己仍是在原型鏈上hasOwnProperty
能夠判斷屬性是否存在於自身,同時也可判斷屬性值爲undefined
的狀況刪除對象的屬性能夠使用delete
方法,只不過此方法的性能並不算太優越
const obj = { b: 1, c: 2 } delete obj.b console.log(obj) // {c: 2}
休息會兒,這篇文章可長哈,按部就班的來。
JavaScript
中將屬性分爲兩種:數據屬性和訪問器屬性。
數據屬性包括:Configurable
、Enumerable
、Writable
、Value
四個屬性描述符
訪問器屬性包括:Configurable
、Enumerable
、Set
、Get
四個屬性描述符
經過對比咱們能夠發現,屬性描述有六類:
Configurable、Enumerable、Writeable、Value、Set、Get
注意:
修改描述符,只能夠經過Object.defineProperty(obj, key, config)修改一個
|| Object.defineProperties(obj,config)修改多個
方法來修改。
例如:
const obj = { a: 1, b: 2, c: 3 } // 修改一個 Object.defineProperty(obj, 'a', { enumerable: true, writable: true, configurable: true }) // 修改多個 Object.defineProperties(person, { a: { enumerable: true, writable: true, configurable: true }, b: { enumerable: true, writable: true, configurable: true } }
Configurable
:是否可經過delete
刪除屬性、是否可從新定義屬性、是否可修改描述符、是否可進行屬性互換。
true
上述操做均可進行const obj = { a: 1, b: 2, c: 3 } Object.defineProperty(obj, 'a', { configurable: true }) delete obj.a Object.defineProperty(obj, 'a', { value: 11 }) Object.defineProperty(obj, 'a', { enumerable: true }) Object.defineProperty(obj, 'a', { set() {} })
false
嚴格模式下報錯,普通模式下過濾操做const obj = { a: 1, b: 2, c: 3 } Object.defineProperty(obj, 'a', { configurable: false }) delete obj.a Object.defineProperty(obj, 'a', { value: 11 }) Object.defineProperty(obj, 'a', { enumerable: true }) Object.defineProperty(obj, 'a', { set() {} })
Enumerable
:是否可枚舉
const obj = { a: 1, b: 2, c: 3 } // 爲 true 的狀況,可遍歷 Object.defineProperty(obj, 'a', { enumerable: true }) for(let item in obj) { console.log(item) // a, b, c 可遍歷到 a } // 爲false的狀況,不可遍歷 Object.defineProperty(obj, 'a', { enumerable: false }) for(let item in obj) { console.log(item) // b, c 遍歷不到 a }
Writable
:是否可修改屬性的值,加上它,將變爲數據屬性
const obj = { a: 1, b: 2, c: 3 } // 爲 true 可修改屬性值 Object.defineProperty(obj, 'a', { writable: true }) obj.a = 2 console.log(obj.a) // 2 // 爲false 不可修改屬性值 嚴格模式下會報錯 Object.defineProperty(obj, 'a', { writable: false }) obj.a = 2 console.log(obj.a) // 1
Value
:屬性的數據值,加上它,將變爲數據屬性
const obj = { a: 1, b: 2, c: 3 } Object.defineProperty(obj, 'a', { value: 11 }) console.log(obj.a) // 11
Set
:寫入屬性時調用,加上它,將變爲訪問器屬性
const obj = { a: 1, b: 2, c: 3 } Object.defineProperty(obj, 'a', { set() { console.log('a的值改變了') } }) obj.a = 2 // a的值改變了
Get
:讀取屬性時調用,加上它,將變爲訪問器屬性
const obj = { a: 1, b: 2, c: 3 } Object.defineProperty(obj, 'a', { get() { console.log('獲取a的值') } }) obj.a // 獲取a的值
數據屬性 --> 訪問器屬性
將 Writable、Value
中的任意一個替換爲 Set、Get
中的任意一個。
訪問器屬性 --> 數據屬性
將 Set、Get
中的任意一個替換爲 Writable、Value
中的任意一個。
示例可接着往下看
想要查看某個屬性的描述,能夠使用Object.getOwnPropertyDescriptor(obj, key)
來查看
const obj = { a: 1 } console.log(Object.getOwnPropertyDescriptor(obj, 'a')) // { value: 1, writable: true, enumerable: true, configurable: true } Object.defineProperty(obj, 'a', { get() { console.log('獲取a的值') } }) console.log(Object.getOwnPropertyDescriptor(obj, 'a')) /* { get: [Function: get], set: undefined, enumerable: true, configurable: true } */
此例咱們能夠驗證 屬性互換
的正確性,當咱們將get
設置爲 a
的描述符時,a
會變爲訪問器屬性
接下文:Object 重識(二)