内建类是可扩展的

一、内建的类,例如Array,Map等也都是可以扩展的(extendable)。
【示例1】这里有一个继承自原生Array的类PowerArray:

  1. // 给 PowerArray 新增了一个方法(可以增加更多)
  2. class PowerArray extends Array {
  3. isEmpty() {
  4. return this.length === 0;
  5. }
  6. }
  7. let arr = new PowerArray(1, 2, 5, 10, 50);
  8. alert(arr.isEmpty()); // false
  9. let filteredArr = arr.filter(item => item >= 10);
  10. alert(filteredArr); // 10, 50
  11. alert(filteredArr.isEmpty()); // false

1、内建的方法例如filter,map等 — 返回的正是子类PowerArray的新对象。它们内部使用了对象的constructor属性来实现这一功能。
2、在上面的例子中,

  1. arr.constructor === PowerArray

3、当arr.filter()被调用时,它的内部使用的是arr.constructor来创建新的结果数组,而不是使用原生的Array。这样我们可以在结果数组上继续使用PowerArray的方法。
4、甚至,我们可以定制这种行为。
5、我们可以给这个类添加一个特殊的静态 getterSymbol.species。如果存在,则应返回 JavaScript 在内部用来在map和filter等方法中创建新实体的constructor。
6、如果我们希望像map或filter这样的内建方法返回常规数组,我们可以在Symbol.species中返回Array,就像这样:

  1. class PowerArray extends Array {
  2. isEmpty() {
  3. return this.length === 0;
  4. }
  5. // 内建方法将使用这个作为 constructor
  6. static get [Symbol.species]() {
  7. return Array;
  8. }
  9. }
  10. let arr = new PowerArray(1, 2, 5, 10, 50);
  11. alert(arr.isEmpty()); // false
  12. // filter 使用 arr.constructor[Symbol.species] 作为 constructor 创建新数组
  13. let filteredArr = arr.filter(item => item >= 10);
  14. // filteredArr 不是 PowerArray,而是 Array
  15. alert(filteredArr.isEmpty()); // Error: filteredArr.isEmpty is not a function

7、正如你所看到的,现在.filter返回Array。所以扩展的功能不再传递。
二、其他集合,例如Map和Set的工作方式类似。它们也使用Symbol.species。

内建类没有静态方法继承

一、内建对象有它们自己的静态方法,例如Object.keys,Array.isArray等。
二、如我们所知道的,原生的类互相扩展。例如,Array扩展自Object。
三、通常,当一个类扩展另一个类时,静态方法和非静态方法都会被继承。
四、但内建类却是一个例外。它们相互间不继承静态方法。
五、Array和Date都继承自Object,所以它们的实例都有来自Object.prototype的方法。但Array.[[Prototype]]并不指向Object,所以它们没有例如Array.keys()(或Date.keys())这些静态方法。
1、这里有一张Date和Object的结构关系图:image.png

2、正如你所看到的,Date和Object之间没有连结。它们是独立的,只有Date.prototype继承自Object.prototype,仅此而已。
3、与我们所了解的通过extends获得的继承相比,这是内建对象之间继承的一个重要区别。