【问题标题】:Base JavaScript object on another object using class and constructor使用类和构造函数将 JavaScript 对象基于另一个对象
【发布时间】:2015-10-13 08:57:50
【问题描述】:

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

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

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

【问题讨论】:

  • 您希望最终结构是什么? JSON 属性将存在于哪里,应该构建什么样的原型链? (或者换句话说,你打算如何使用这个......)

标签: javascript prototype ecmascript-6


【解决方案1】:

如果json 在每个实例中都是唯一的,您应该更改this 而不是this.prototype。您可以为此使用Object.assign

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

Object.assign 将参数 1-n 中的 enumerableown 属性复制(通过引用)到参数 0。它是 _.assign(又名 @ 987654330@)。

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

【讨论】:

  • 这就是我的想法,但有人告诉我Object.assign(this, ..)一个坏主意。不知道为什么,除了你无法控制的意外副作用。
  • 副作用正是你在这里想要实现的——在第一个参数中改变对象。
  • Object.assign(this, ...) 不是本质上是一件坏事。与任何其他语言功能或模式一样,了解如何使用它很重要。如果你想扩展一个对象而不是增加它,标准模式是const extended = Object.assign({}, baseObject, extraObject),但这不是你想要的(因为它实际上不会更新你的类实例)。
  • 唯一可能发生的副作用是base 的属性将优先于A 中定义的方法,因为它们将直接成为实例的一部分,而后者将在他们的prototype。如果这是你想要的那种行为,那就继续吧。如果您想避免这种情况,您可能需要在插入base 的任何属性之前检查它是否还不是A.prototype 的一部分。它可以通过Object.keys(base).filter((k) => !k in A.prototype).forEach 之类的方式轻松执行。但这开始有点棘手。
【解决方案2】:

如果您的 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. 从概念上讲,我发现第一个解决方案更加优雅。

【讨论】:

  • 可以 Object.assign(this.prototype, base),但这会导致非常奇怪的行为 - 每次创建新实例时所有实例都会有效地改变。那将是一个坏主意
  • 是的,非常糟糕的主意。你可以做的就是在外面 A的构造函数。
  • 实际上,它看起来不起作用(至少使用 babel)。 this.prototype 仍然是 undefinedconstructor 中(我个人认为完全可以且更安全)。
  • 是的,如果目标是影响所有实例,这就是答案。我认为 JSON 可能每个实例都是唯一的,因为它是一个构造函数 arg。
  • 啊,好的。我不知道。
猜你喜欢
  • 1970-01-01
  • 2019-01-17
  • 1970-01-01
  • 1970-01-01
  • 2017-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-17
相关资源
最近更新 更多