Object 重識(一)

內容有點兒多,將分爲兩篇內容與你們分享。有的地方確實難以理解,能夠多動手實現一下,看看效果。javascript

一直據說有這麼一句話,在JavaScript中,一切皆爲對象。 java

經本人慎重研究以後發現,此言的確不虛。(這不廢話麼,虛不虛的還用你說。)函數

今天斗膽跟你們一塊兒討論一下JavaScript重的Object。瞭解Object背後的 -- 生活性能

閱讀間隙,還得多注意休息喲~this

1. 對象的建立

開始第一個小問題,看一下如何建立一個對象。建立對象有四(shi)種方式。如下幾種方式均可建立一個對象,只不過建立以後的表現稍有不一樣。具體表現爲原型和this的指向問題。有興趣的讀者可點擊查看相關文章。在這裏咱們就不詳細介紹了。(偷個懶)prototype

完全弄懂JavaScript原型問題指針

深刻理解JavaScript的 this 指針code

注意點:對象

四種方式建立對象,除了原型this指針表現不一樣,構造函數指向也有不一樣。(此時說明的是不手動指定構造函數的狀況下)ip

  • 字面量方式建立的對象。構造函數爲 function Object() {}
  • 構造函數建立。構造函數爲函數自己
  • Object.create建立的對象,構造函數爲入參origin的構造函數
  • class 方式建立,會將自己也做爲構造函數。

1.1 字面量方式建立

const obj = {} // 構造函數爲 [Function: Object]

1.2 構造函數建立

function Obj() {}

const obj = new Obj() // 構造函數爲 [Function: origin]

1.3 Object.create 建立

const origin = {a: 1, b: 2}

const target = Object.create(origin) // 構造函數爲 origin 的構造函數

1.4 class方式建立

class Origin {}

const target = new Origin() // 構造函數 [Function: Origin]

2. 屬性和方法

注:

  • 官方版

    • 屬性是這個對象的屬性,方法是這個對象所擁有的功能
  • 通俗版

    • 屬性是一個值,不可執行。
    • 方法爲一個函數,可執行。

2.1 屬性和方法獲取

1.獲取肯定的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 (){}
2.獲取須要計算的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是一個函數,才能執行。

2.2 如何判斷對象中含有某個值

在此段內容開始以前,先說一個小問題,如何判斷對象中是否含有某個key值?

1. 使用 2.1中的屬性獲取
  • 只需判斷是否爲 undefined 便可。
  • 此方法有一個缺陷,若是此值確實爲 undefined,則會出現判斷失誤的狀況
const obj = {
  c: undefined
}

console.log(obj.c === 'undefined') // 判斷爲true,可是obj中確實含有c這個key
2. 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是存在於對象自己仍是在原型鏈上。此狀況,咱們須要用到下面這種方法。

3. 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的狀況

2.3 刪除對象的屬性

刪除對象的屬性能夠使用delete方法,只不過此方法的性能並不算太優越

const obj = {
  b: 1,
  c: 2
}

delete obj.b
console.log(obj) // {c: 2}

休息會兒,這篇文章可長哈,按部就班的來。

2.4 屬性分類

JavaScript中將屬性分爲兩種:數據屬性和訪問器屬性

數據屬性包括:ConfigurableEnumerableWritableValue 四個屬性描述符

訪問器屬性包括:ConfigurableEnumerableSetGet 四個屬性描述符

經過對比咱們能夠發現,屬性描述有六類:

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
  }
}
1. 描述符介紹

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的值
2. 屬性互換:

數據屬性 --> 訪問器屬性

Writable、Value 中的任意一個替換爲 Set、Get 中的任意一個。

訪問器屬性 --> 數據屬性

Set、Get 中的任意一個替換爲 Writable、Value 中的任意一個。

示例可接着往下看

3. 獲取某個屬性的描述(查看此屬性是數據屬性仍是訪問器屬性)

想要查看某個屬性的描述,能夠使用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 重識(二)

相關文章
相關標籤/搜索