[翻译]扩展内置类

扩展内置类

javascript内置类比如数组,哈希和其他内置类等都是可扩展的。

比如,这里的PowerArray就是从原生Array继承而来的

// 给原生数组添加额外方法(还可以添加更多)
class PowerArray extends Array {
    isEmpty() {
        return this.length === 0;
    }
}

let arr = new PowerArray(1251050);
alert(arr.isEmpty()); // false

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

请注意一个有趣的现象。内置方法,比如filter,map 和其他方法 - 都返回了继承类的新实例。这是由它们的constructor属性所导致的。

在在上述例子中就是,

arr.constructor === PowerArray;

所以调用arr.filter()时, 会在方法内部为返回结果创建新数组,这个新数组确切地说是使用new PowerArray的方式而不是new Array的方式创建的。这很好,因为我们可以在返回结果上继续使用PowerArray的方法。

甚至,我们可以定制这一行为。

我们可以为这个类添加一个特殊的静态取值函数Symbol.species。它会返回 JavaScript 默默地用来在mapfilter等方法中创建新实例的构造函数。

假如我们想要内置方法比如mapfilter中返回常规的数组,那么我们可以在Symbol.species返回内置数组Array,就像下面这样:

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

    // 内置方法将使用下面函数的返回值作为构造函数
    static get [Symbol.species] {
        return Array
    }
}

let arr = new PowerArray(1251050);
alert(arr.isEmpty()); // false

// filter方法使用 arr.constructor[Symbol.species] 作为构造函数来创建返回的新数组
let filteredArr = arr.filter(item => item >= 10);

// filteredArray 的构造函数不是PowerArray, 而是Array
alert(filteredArr.isEmpty()); // Error: filteredArr.isEmpty is not a function

正如你所看到的,现在 .filter 返回了 Array 类型。因此继承的方法并没有进一步的传递下来。

内置类中不存在静态继承

内置对象都有自己的静态方法,比如Object.keysArray.isArray等。

众所周知,内置类之间会彼此继承。比如,Array 继承自 Object

一般来说,当一个类继承自另一个时,静态和常规方法都会被继承。

所以,当Rabbit extends Animal,其结果是:

  1. 静态方法Rabbit.methods继承自Animal.methods,因为Rabbit.[[prototype]] = Animal
  2. 实例中的常规方法new Rabbit().methods也会继承,因为Rabbit.prototype.[[prototype]] = Animal.prototype

这在 静态属性和静态方法 章节中已经仔细解释过了。

但是,内置类除外。它们并不能在彼此之间继承静态属性和方法。

比如,ArrayDate对象都继承自Object, 因此它们的实例拥有Object.prototype上的方法。但是Array.[[prototype]]并不指向Object。所以,存在Object.keys()方法,却并不存在Array.keys()Date.keys()方法。

下图展示了DateObject的关系

注意,DateObject之间并没有联系。ObjectDate两个类都是独立存在的。

仅仅是,Date.prototype继承自Object.prototype

posted @ 2019-11-21 00:02  rencoo  阅读(218)  评论(0编辑  收藏  举报