返回课程

类扩展对象?

重要性:3

众所周知,所有对象通常继承自 Object.prototype 并获得对“通用”对象方法(如 hasOwnProperty 等)的访问权限。

例如

class Rabbit {
  constructor(name) {
    this.name = name;
  }
}

let rabbit = new Rabbit("Rab");

// hasOwnProperty method is from Object.prototype
alert( rabbit.hasOwnProperty('name') ); // true

但是,如果我们明确地写出来,比如 "class Rabbit extends Object",那么结果会与简单的 "class Rabbit" 不同吗?

有什么区别?

以下是一个代码示例(它无法运行 - 为什么?如何修复?)。

class Rabbit extends Object {
  constructor(name) {
    this.name = name;
  }
}

let rabbit = new Rabbit("Rab");

alert( rabbit.hasOwnProperty('name') ); // Error

首先,让我们看看为什么后面的代码无法运行。

如果我们尝试运行它,原因就会变得很明显。继承类的构造函数必须调用 `super()`。否则,`“this”` 将不会被“定义”。

所以,以下是修复方法

class Rabbit extends Object {
  constructor(name) {
    super(); // need to call the parent constructor when inheriting
    this.name = name;
  }
}

let rabbit = new Rabbit("Rab");

alert( rabbit.hasOwnProperty('name') ); // true

但这还不是全部。

即使修复后,`“class Rabbit extends Object”` 和 `class Rabbit` 之间仍然存在一个重要的区别。

如我们所知,“extends” 语法设置了两个原型

  1. 在构造函数的 `“prototype”` 之间(用于方法)。
  2. 在构造函数本身之间(用于静态方法)。

在 `class Rabbit extends Object` 的情况下,这意味着

class Rabbit extends Object {}

alert( Rabbit.prototype.__proto__ === Object.prototype ); // (1) true
alert( Rabbit.__proto__ === Object ); // (2) true

因此,`Rabbit` 现在可以通过 `Rabbit` 访问 `Object` 的静态方法,例如

class Rabbit extends Object {}

// normally we call Object.getOwnPropertyNames
alert ( Rabbit.getOwnPropertyNames({a: 1, b: 2})); // a,b

但是,如果我们没有 `extends Object`,那么 `Rabbit.__proto__` 不会被设置为 `Object`。

以下是演示

class Rabbit {}

alert( Rabbit.prototype.__proto__ === Object.prototype ); // (1) true
alert( Rabbit.__proto__ === Object ); // (2) false (!)
alert( Rabbit.__proto__ === Function.prototype ); // as any function by default

// error, no such function in Rabbit
alert ( Rabbit.getOwnPropertyNames({a: 1, b: 2})); // Error

因此,在这种情况下,`Rabbit` 不会提供对 `Object` 的静态方法的访问。

顺便说一下,`Function.prototype` 也具有“通用”函数方法,例如 `call`、`bind` 等。它们最终在两种情况下都可用,因为对于内置的 `Object` 构造函数,`Object.__proto__ === Function.prototype`。

以下是图片

所以,简而言之,有两个区别

class Rabbit class Rabbit extends Object
需要在构造函数中调用 `super()`
Rabbit.__proto__ === Function.prototype Rabbit.__proto__ === Object