开发者问题收集

使用类和构造函数将 JavaScript 对象作为另一个对象的基础

2015-10-13
287

ES6 引入了 classextendsconstructor 等,使得基于原型的继承变得非常容易。我想将通过类的构造函数构造的对象基于另一个对象。在这种构造对象的新语法方式中,最简洁的方法是什么?

class A {
  constructor(json) {
     let base = JSON.parse(json);
     this.prototype = base; // ????
  }
}

我会使用 extends ,但由于对象被传递下来,因此这里没有其他类定义

2个回答

如果 json 对于每个实例都是唯一的,则您应该更改 this 而不是 this.prototype 。您可以使用 Object.assign 来实现此目的:

class A {
  constructor(json) {
     let base = JSON.parse(json);
     Object.assign(this, base);
  }
}

Object.assign enumerable own 属性(通过引用)从参数 1-n 复制到参数 0。它是 _.assign (又名 _.extend )的本机实现。

相反,如果您想对 all 实例使用单个 json ,则无需将其传递给构造函数。请参阅@Quentin Roy 的回答。

joews
2015-10-13

如果您的 json 对象是构造函数的参数,则它不能成为原型链的一部分。正如 @joews 指出的那样,在这种情况下,您唯一能做的就是在类的构造函数中复制其属性。

如果您希望 json 对象成为原型链的一部分,我会这样做:

var base = JSON.parse(json)

// Creates a Base class based on the base object.
class Base {} // or function Base(){} which is exactly the same.
Base.prototype = base;

// Extends it.
class A extends Base {
  constructor() {
  }
}

编辑:

作为替代方案,您可以这样做:

class A {
  constructor() {
  }
}
Object.assign(A.prototype, JSON.parse(json));

但我发现以前的解决方案更简洁,因为 base 是原型链中一个独特的原型,而不是与 A 的原型合并。这有几个优点:

  1. 在后一种解决方案中,如果 base 的属性具有相同的名称,则它将覆盖 A 的属性。在第一个解决方案中,两个属性仍将存在(尽管 A 的属性具有优先级,但您仍可以使用 super 访问父级的属性)。
  2. 使用第一个解决方案,您可以执行 aInstance instanceof Base 。您不能使用后者。
  3. 从概念上讲,我发现第一个解决方案更加优雅。
Quentin Roy
2015-10-13