【JS】扩展内建类 - Symbol.species

Symbol.species 是个函数值属性,其被构造函数用以创建派生对象,

Symbol.species访问器属性允许子类覆盖对象的默认构造函数。

 

JS内建类可以被扩展

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

const arr = new MyArray(1,2,3,4,5)
console.log(arr.isEmpty()); // false

const newArr = arr.filter(item => item > 3)
console.log(newArr.length,newArr.isEmpty()); 2,false

我们可以发现当 arr.filter() 被调用时,它的内部使用的是 arr.constructor 来创建新的结果数组,而不是使用原生的 Array。因此我们可以在结果数组上继续使用 MyArray 的方法。

 

我们可以给这个类添加一个特殊的静态 getter Symbol.species。如果存在,则应返回 JavaScript 在内部用来在 map 和 filter 等方法中创建新实体的 constructor

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

     static get [Symbol.species](){
         return Array
     }
 }

const arr = new MyArray(1,2,3,4,5)
console.log(arr.isEmpty()); // false

const newArr = arr.filter(item => item > 3)
console.log(newArr.length,newArr.isEmpty()); // newArr.isEmpty is not a function

这时,arr.filter()创建的数组对象是使用Array创建的,所以不能使用MyArray.prototype上的方法。

 

 

内建类的静态方法不能被继承

内建对象有它们自己的静态方法,例如 Object.keysArray.isArray 等。

通常,当一个类扩展另一个类时,静态方法和非静态方法都会被继承。但内建类却是一个例外。它们相互间不继承静态方法。

下图中,Array 和 Date 都继承自 Object,所以它们的实例都有来自 Object.prototype 的方法。但 Array.[[Prototype]] 并不指向 Object,所以它们没有例如 Array.keys()(或 Date.keys())这些静态方法。

与普通类的继承相比,内建类之间的extends只创建了一个[[Prototype]]引用,Child.[[prototype]] = Parent.prototype

 

 

posted @ 2022-10-29 19:29  Ahoge的笔记本  阅读(261)  评论(0编辑  收藏  举报