Object重識(二)

接上文:Object重識(一)javascript

3. 對象繼承

對象繼承,咱們不介紹名詞,不說是什麼樣的繼承,只從頭看下每一個繼承方式的不足,並介紹如何補充java

3.1 最簡單的繼承

function A (name) {
  this.name = name
}

function B () {}

B.prototype = new A('張三')
console.log(new B("李四").name) // 張三

此方法是將 B 的原型直接指向 A 的原型,從而達到繼承的目的。Object.create方式建立對象等同於此方式。數組

優點:函數

可達到屬性複用。this

缺陷:spa

沒法在實例化的時候傳遞參數,不可配置。上述示例中 AB 的名稱都爲 張三。即便咱們在實例化 B 的時候傳入一個名稱。prototype

3.2 改進版

改進版可在實例化的時候添加參數code

function A (name) {
  this.name = name;
}

function B (name) {
  A.call(this, name)
}

console.log(new B('李四').name) // 李四

優點:對象

可實現定製化,支持傳參配置繼承

缺陷:

沒法複用,全部內容都經過構造函數定義

3.3 結合版

function A (name) {
  this.name = name;
}
A.prototype.address = '中國'

function B (name) {
  A.call(this, name)
}
B.prototype = new A();

const b = new B('李四')
console.log(b.name) // 李四
console.log(b.address) // 中國

總結:

此繼承方式也不是完整版,只是讓你們瞭解繼承的實現方式。像什麼 寄生繼承、寄生組合繼承。我們就多囉嗦了,容易越看越亂。有興趣的讀者能夠以後再跟你們分享或者自行查閱。

3.4 ES6 繼承

有了ES6以後感受空氣都甜了。以前複雜的繼承寫法都變得特別簡單。看栗子↓↓↓↓↓

class A {
  constructor (name) {
    this.name = name;
  }
}
class B extends A {
  constructor (name) {
    super(name)
  }
}

const b = new B('李四')

console.log(b.name)

class方式建立對象注意點:

  • 寫在 構造函數constructor 中的方法都屬於自身的方法。
  • 寫在構造函數constructor 以外的方法都屬於原型方法

舉慄說明:

class A {
  constructor () {
    this.log = function () {
      console.log('111111')
    }
  }
  log () {
    console.log('222222')
  }
}

const a = new A()
a.log() // 111111 -- 原型鏈的查找問題

console.log(a.log)
/*
    ƒ () {
    console.log('111111')
  }
*/

console.log(a.__proto__.log)
/*
  ƒ log () {
    console.log('222222')
  }
*/

4. 對象操做

4.1 對象轉字符串

使用 JSON.stringify 方法將對象轉換爲字符串顯示

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

const strObj = JSON.stringify(obj)

console.log(strObj) // {"a":1,"b":2,"c":3}

注意點:

JSON.stringify(obj, replacer, space) 接收三個參數

  • obj 被轉換的對象
  • replacer 能夠是 函數 或 數組。爲數組,只轉換數組中的值
const obj = {
  a: 1,
  b: 2,
  c: 3
}

// 第二個參數爲數組
console.log(JSON.stringify(obj, ['a', 'b'])) // {"a":1,"b":2}

// 第二個參數爲函數
function replacer(key, value) {
  if (value === 1){
    return undefined
  }
  return value
}
console.log(JSON.stringify(obj, replacer)) // {"b":2,"c":3}
  • space 能夠爲數字或字符串,添加輸出結果中的間距。最大間距數量爲 10 。最小爲 0
const obj = {
  a: 1,
  b: 2,
  c: 3
}

// 爲數字
console.log(JSON.stringify(obj, null, 2))
/*
{
  "a": 1,
  "b": 2,
  "c": 3
}
*/

// 爲字符串
console.log(JSON.stringify(obj, null, '-')) 
/*
{
-"a": 1,
-"b": 2,
-"c": 3
}
*/

4.2 對象轉換爲數組

1. Object.keys 返回對象的 key 值組成的數組
2. Object.values 返回對象的value值組成的數組
3. Object.entries 返回對象的 key 值和value值組成的數組
const obj = {
  a: 1,
  b: 2,
  c: 3
}

console.log(Object.keys(obj)) // [ 'a', 'b', 'c' ]
console.log(Object.values(obj)) // [ 1, 2, 3 ] 
console.log(Object.entries(obj)) // [ [ 'a', 1 ], [ 'b', 2 ], [ 'c', 3 ] ]

上述方法會用就能夠,沒太多須要注意的點。

4.3 對象擴展,密封,凍結

1. 對象拓展

什麼是對象拓展?

1.1小節中建立的對象均可以添加新的屬性和方法,這就叫對象拓展。可使用 Object.isExtensible 方法查看。

function B () {}

const a = {}
const b = new B()

console.log(Object.isExtensible(a)) // true
console.log(Object.isExtensible(b)) // true

禁止對象拓展, 可以使用 Object.preventExtensions 方法

function B () {}

const a = {}
const b = new B()

// 禁止對象拓展
Object.preventExtensions(a)
Object.preventExtensions(b)

console.log(Object.isExtensible(a)) // false
console.log(Object.isExtensible(b)) // false
2. 對象密封 Object.seal

對象密封能夠理解爲字面的意思。就是把一個對象密封起來。

密封的對象不可拓展(不能添加新屬性),不可刪除屬性,不能修改已有屬性的屬性描述符(writeable、value等)

將一個對象密封,可使用Object.seal方法

一樣,查詢一個對象是不是密封對象,可使用Object.isSealed方法

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

// 密封一個對象
Object.seal(obj)

// 嘗試刪除
delete obj.a
console.log(obj) // { a: 1, b: 2, c: 3 }

// 嘗試添加
obj.d = 4
console.log(obj) // { a: 1, b: 2, c: 3 }

// 查詢對象是不是密封狀態
console.log(Object.isSealed(obj)) // true

// 嘗試修改原有屬性值
obj.a = 4
console.log(obj) // { a: 4, b: 2, c: 3 }

注意:

雖然將對象密封了,可是依舊能夠修改原有的屬性值。若是想讓一個對象不可更改,能夠用到下面這個方法。

3. 對象凍結 Object.freeze

對象凍結顧名思義就是將對象的全部屬性都凍結住,不可修改,不可增刪。可使用Object.freeze方法凍結一個對象。查看一個對象是不是凍結對象可使用Object.isFrozen() 方法。

const obj = {
  a: 1,
  b: 2,
  c: 3
}
// 凍結一個對象
Object.freeze(obj)

// 嘗試新增
obj.d = 4
console.log(obj) //{ a: 1, b: 2, c: 3 }

// 嘗試刪除
delete obj.a
console.log(obj) //{ a: 1, b: 2, c: 3 }

// 嘗試修改
obj.a = 4
console.log(obj) //{ a: 1, b: 2, c: 3 }

// 查看對象是否凍結
Object.isFrozen(obj) // true

看吧,凍結以後的對象你是不能對它作操做的。

可是………………

這種狀況下能夠修改

const obj = {
  a: 1,
  b: 2,
  c: {
    d: 4
  }
}
Object.freeze(obj)

obj.c.d = 11
console.log(obj.c) //{ d: 11 }

也就是說,凍結對象只能凍結一層,不能深層次凍結,若是須要深層次凍結,則須要遞歸的凍結每一個值爲對象的屬性。

4.4 對象解構

此操做等同於數組解構,不一樣的是,對象會根據屬性值進行解構操做。話很少說,小栗子來看下

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

// 普通解構
let {a, b} = obj
console.log(a, b) // 1, 2

// 帶默認值的解構,解構不到時,賦值爲默認值
let {a = 0, b = 0, d = 0} = obj
console.log(a,b, d) // 1,2,0

// 解構並重命名
let {a: newA, b: newB} = obj
console.log(newA, newB) // 1, 2

// 默認值 and 重命名
let {d: newA = 0, b: newB = 0} = obj
console.log(newA, newB) // 0, 2

注意點:

  • 解構能夠添加默認值
  • 解構能夠重命名
  • 可使用重命名 and 默認值並存的方式解構對象

4.5 對象拷貝和對象比較 Object.assign、Object.is

1. 對象拷貝

Object.assign 能夠實現對象的複製,合併,深拷貝等操做,須要注意的點是:繼承的屬性和不可枚舉(enumerable爲false)的屬性不能拷貝

  • 對象拷貝
// 深拷貝

const obj1 = {
  d: 4,
  e: 5
}

const a = Object.assign({}, obj1)

console.log(a)

obj1.d = 2
console.log(a) // 修改以後不會變更a的值
  • 對象合併
const obj = {
  a: 1,
  b: 2,
  c: 3
}

const obj1 = {
  a: 4,
  e: 5
}

const a = Object.assign(obj, obj1)

console.log(a) // { a: 4, b: 2, c: 3, e: 5 }

合併後,若是第二個參數中有和第一個參數相同的屬性,則第二個參數的屬性會覆蓋第一個參數的屬性。

2. 對象比較

以前的工做中,咱們會知道這樣一句話,NaN不等於任何東西,包括它自身 。那麼咱們用Object.is來試一下。

此方法用來比較兩個對象是否相等。

Object.is(NaN, NaN) // true
Object.is(+0, -0) // false

除去上面這種案例,其餘的表現與 === 相同

4.6 ?.?? (可選鏈和空值合併)

1. 可選鏈 ?.

平常工做中,像下面這種代碼很是常見。

const obj = {
  result: {
    a: 1
  }
}

let result = obj.result && obj.result.a;

固然,有了可選鏈以後,咱們就不須要這麼麻煩了 ,上述代碼可改寫成如下方式:

const obj = {
  result: {
    a: 1
  }
}

let result = obj.result?.a;

若是obj.resultundefined 或者 null 時,會中斷操做而返回undefined 或者 null

此方法也可用於函數

const obj = {
  result: function (){

  }
}

obj.result?.();

用於數組:

const arr = []
arr?.[0]

用於表達式:

const obj = {
  parentResult
}

obj?.['parent' + 'Result']

可連用:

const arr = [[[1]]]

arr?.[0]?.[0]?.[0]

可選鏈具備短路功能,若是左邊的操做數爲 undefinednull ,則會中斷表達式計算。 (相似於 &&)

可是,此方式不能用於賦值

obj?.['parent'] = 1
2. 空值合併

若是咱們相給一個值賦默認值,一般是這麼作

let obj = {}
let result = obj.a || 1

如今,咱們能夠這麼作

let obj = 0
let result = obj.a ?? 1

空值合併一樣具備短路功能,當左邊不爲null時,中斷操做。(相似於 || )

注意:

控制合併不能與 &&|| 連用喲。會出現問題。

?.??合用

let obj = {
  a: 1,
  b: 2
};
let result = obj?.a ?? 0;
console.log(result); // 1

好了,every body. 今天要分享的內容就到這裏了。我們下次再見~~

相關文章
相關標籤/搜索