在javascript中扩展对象与根本不扩展之间有区别吗?

Kas*_*per 6 javascript ecmascript-6

我发现我可以像这样扩展 Object:

class MyObject extends Object {}
Run Code Online (Sandbox Code Playgroud)

与此有什么区别并且根本不扩展,如下所示:

class MyObject {}
Run Code Online (Sandbox Code Playgroud)

我问这个的原因是因为我有以下mixin:

const MapMixin = (Base = Object) => class extends Base {
  static from(array) {
    return new this(Object.assign(...array.map(([key, value]) => ({[key]: value}))));
  }

  map(...args) {
    return this.constructor.from(this.entries().map(...args));
  }

  entries() {
    return Object.entries(this);
  }
};
Run Code Online (Sandbox Code Playgroud)

这个 mixin 可以这样使用:

class MyObject extends MapMixin(MyBaseClass) {}
Run Code Online (Sandbox Code Playgroud)

但是如果没有基类,我现在已经指定它然后Object作为默认扩展:

class MyObject extends MapMixin() {}
Run Code Online (Sandbox Code Playgroud)

所以我想知道,这是否实际上与根本不扩展任何内容相同。

sen*_*lar 5

我不知道这里的其他答案是否清楚,但区别在于静态继承。

class关键字之前,JavaScript 中的继承一直非常注重实例继承。没有人(我见过)愿意经历让一个类/构造函数从超类/构造函数继承静态成员的麻烦。更不用说做到这一点的唯一方法是通过非标准__proto__属性。

因此,当我们今天查看一个扩展另一个类的类时,我们会考虑继承在该类的实例之间是如何工作的。例如,extendsObject或什么都没有,都是一样的,因为实例本质上是从Object作为基类继承的。

class A {}
class B extends Object {}

let a = new A()
let b = new B()

// a.__proto__.__proto__ === b.__proto__.__proto__ === Object.prototype 
Run Code Online (Sandbox Code Playgroud)

但是,可能不清楚或不太清楚extends关键字的作用不仅仅是为实例设置继承。它还设置了类构造函数之间的继承。所以对于B上面,使用extends也意味着Object.setPrototypeOf(B, Object)B 在后台被调用。所以,例如:

class A {} // A constructor inherits nothing (is a basic Function type)
class B extends Object {} // B inherits from Object

// A.setPrototypeOf === undefined
// B.setPrototypeOf === Object.setPrototypeOf
Run Code Online (Sandbox Code Playgroud)

B, extends Object, 从 继承所有静态方法ObjectA而不扩展任何东西,不会。

区别在于B.prototype(或B.prototype.__proto__) - 实例继承自B.__proto__什么,以及- 类构造函数继承自什么。扩展Object与否不会影响prototype实例从其继承的内容或内容,但会影响类的__proto__或静态继承。