类扩展对象?
众所周知,所有对象通常继承自 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” 语法设置了两个原型
- 在构造函数的 `“prototype”` 之间(用于方法)。
- 在构造函数本身之间(用于静态方法)。
在 `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 |