Javascript 擴(kuò)展內(nèi)建類

2023-02-17 10:53 更新

內(nèi)建的類,例如 ?Array?,?Map? 等也都是可以擴(kuò)展的(extendable)。

例如,這里有一個(gè)繼承自原生 Array 的類 PowerArray

// 給 PowerArray 新增了一個(gè)方法(可以增加更多)
class PowerArray extends Array {
  isEmpty() {
    return this.length === 0;
  }
}

let arr = new PowerArray(1, 2, 5, 10, 50);
alert(arr.isEmpty()); // false

let filteredArr = arr.filter(item => item >= 10);
alert(filteredArr); // 10, 50
alert(filteredArr.isEmpty()); // false

請注意一個(gè)非常有趣的事兒。內(nèi)建的方法例如 filter,map 等 —— 返回的正是子類 PowerArray 的新對象。它們內(nèi)部使用了對象的 constructor 屬性來實(shí)現(xiàn)這一功能。

在上面的例子中,

arr.constructor === PowerArray

當(dāng) arr.filter() 被調(diào)用時(shí),它的內(nèi)部使用的是 arr.constructor 來創(chuàng)建新的結(jié)果數(shù)組,而不是使用原生的 Array。這真的很酷,因?yàn)槲覀兛梢栽诮Y(jié)果數(shù)組上繼續(xù)使用 PowerArray 的方法。

甚至,我們可以定制這種行為。

我們可以給這個(gè)類添加一個(gè)特殊的靜態(tài) getter Symbol.species。如果存在,則應(yīng)返回 JavaScript 在內(nèi)部用來在 map 和 filter 等方法中創(chuàng)建新實(shí)體的 constructor。

如果我們希望像 map 或 filter 這樣的內(nèi)建方法返回常規(guī)數(shù)組,我們可以在 Symbol.species 中返回 Array,就像這樣:

class PowerArray extends Array {
  isEmpty() {
    return this.length === 0;
  }

  // 內(nèi)建方法將使用這個(gè)作為 constructor
  static get [Symbol.species]() {
    return Array;
  }
}

let arr = new PowerArray(1, 2, 5, 10, 50);
alert(arr.isEmpty()); // false

// filter 使用 arr.constructor[Symbol.species] 作為 constructor 創(chuàng)建新數(shù)組
let filteredArr = arr.filter(item => item >= 10);

// filteredArr 不是 PowerArray,而是 Array
alert(filteredArr.isEmpty()); // Error: filteredArr.isEmpty is not a function

正如你所看到的,現(xiàn)在 .filter 返回 Array。所以擴(kuò)展的功能不再傳遞。

其他集合的工作方式類似

其他集合,例如 Map 和 Set 的工作方式類似。它們也使用 Symbol.species。

內(nèi)建類沒有靜態(tài)方法繼承

內(nèi)建對象有它們自己的靜態(tài)方法,例如 Object.keysArray.isArray 等。

如我們所知道的,原生的類互相擴(kuò)展。例如,Array 擴(kuò)展自 Object。

通常,當(dāng)一個(gè)類擴(kuò)展另一個(gè)類時(shí),靜態(tài)方法和非靜態(tài)方法都會(huì)被繼承。這已經(jīng)在 靜態(tài)屬性和靜態(tài)方法 中詳細(xì)地解釋過了。

但內(nèi)建類卻是一個(gè)例外。它們相互間不繼承靜態(tài)方法。

例如,Array 和 Date 都繼承自 Object,所以它們的實(shí)例都有來自 Object.prototype 的方法。但 Array.[[Prototype]] 并不指向 Object,所以它們沒有例如 Array.keys()(或 Date.keys())這些靜態(tài)方法。

這里有一張 Date 和 Object 的結(jié)構(gòu)關(guān)系圖:


正如你所看到的,Date 和 Object 之間沒有連結(jié)。它們是獨(dú)立的,只有 Date.prototype 繼承自 Object.prototype,僅此而已。

與我們所了解的通過 extends 獲得的繼承相比,這是內(nèi)建對象之間繼承的一個(gè)重要區(qū)別。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)