【问题标题】:How to handle object definition vs instantiation in JavaScript?如何在 JavaScript 中处理对象定义与实例化?
【发布时间】:2014-02-10 18:13:43
【问题描述】:

我正在构建一个国际象棋应用程序,并且遇到了一个关于 JavaScript 中对象定义和实例化之间差异的问题。例如,我想通过Matrix 模型将我的Board 模型(和视图)与其表示(嵌套数组)分开:

var Matrix = function(n, m) {
    // builds an n*m nested array
    // e.g. a 2x3 array would look like this:
    // [[0, 0], [0, 0], [0, 0]]
};

// A setter, which takes a `Point` object and correctly updates the nested array
Matrix.prototype.set = function(pt, obj) {
    this.state[pt.y][pt.x] = obj;
};

// A custom `each` method that iterates over the nested array
Matrix.prototype.each = function(fn) {
  // executes `fn` against every (x,y) in the nested array
};

// etc.

然后Board 看起来像这样:

var Board = function(n, m) {
    Matrix.call(this, n, m);

    // now use `Matrix`'s `set` method to place pieces on the board.
};

Board.prototype = Matrix.prototype;

// etc.

我的问题实际上在于Board 的定义。当我实例化一个新的Board 对象时,我希望它继承Matrix,然后使用Matrix 的方法在板上设置棋子。但问题是Board 在实例化时无法访问Matrix 的方法,因为这种关系仍在定义中。

试图解决这个问题已经澄清了this question 的答案。似乎问题在于Board 不是Matrix 的真正子类。在代码实际执行之前,不会设置这种关系。处理这种关系的 JavaScript 式方式是什么?

【问题讨论】:

  • Board.prototype = Matrix.prototype; 是个坏主意。你想要Board.prototype = Object.create(Matrix.prototype);(如果需要,可以为Object.create 的相关功能子集使用垫片)。

标签: javascript inheritance prototype subclass


【解决方案1】:

但问题是 Board 在实例化时无法访问 Matrix 的方法,因为这种关系仍在定义中。

没有。当您在Board 上使用new operator 时,首先将定义关系(“原型链”),然后在新实例上调用Board 构造函数,它可以在其中调用Matrix实例上的函数或添加实例属性,如.state。您可以使用原型继承的set 方法而不会出现任何问题。

看着Why is inheritance only defined at compile-time?

在 JavaScript 中,继承是在运行时设置的。您可以声明函数体(使用其中的继承方法),然后设置原型,然后实例化对象。

Board.prototype = Matrix.prototype;

Don't do that。你想要Board.prototype = Object.create(Matrix.prototype)

【讨论】:

  • 我没有看到对此投反对票的原因,Bergi 对当您实际尝试使用 Board 构造函数时发生的情况非常正确。
  • 我认为这个答案不值得反对。我假设 "...构造函数将在新实例上调用" 指的是 Matrix 构造函数。
  • @cookiemonster:实际上,我确实提到了Board 构造函数。它确实调用Matrix,当然。
  • 当然你不是说:"当你调用 new Board 时,首先定义关系(“原型链”),然后 Board 构造函数将是调用了新实例。” 我以为你指的是Matrix
  • @cookiemonster:是的,这就是我要说的。您可能想阅读有关 how the new operator works 的链接文档 :-)
【解决方案2】:

这是不正确的:

Board.prototype = Matrix.prototype;

请改为执行此操作,以便对 Board.prototype 的添加不会影响 Matrix.prototype

Board.prototype = Object.create(Matrix.prototype);

现在Board.prototype 是一个继承自Matrix.prototype 的空对象。


我看不出为什么您从 Board 创建的对象将无法访问来自 Matrix.prototype 的方法,所以我认为您可能正在覆盖或隐藏 Matrix.prototype 方法。

代码中的// etc. 部分可能是问题所在。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-13
    • 1970-01-01
    • 2011-07-02
    • 1970-01-01
    • 1970-01-01
    • 2019-12-28
    • 1970-01-01
    相关资源
    最近更新 更多