如何在JavaScript中处理对象定义与实例化?

时间:2014-02-10 18:13:44

标签: javascript inheritance prototype subclass

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

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式方式是什么?

2 个答案:

答案 0 :(得分:2)

  

但问题是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)

答案 1 :(得分: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.部分可能就是问题。