0

I am building a chess application and am running into an issue about the difference between object definition and instantiation in JavaScript. For example, I want to separate my Board model (and view) from its representation (a nested array) via a Matrix model:

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.

And then Board looks like this:

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.

My issue is really in the definition of Board. When I instantiate a new Board object, I would like for it to subclass Matrix and then use Matrix's methods to set pieces on the board. But the problem is that Board does not have access to Matrix's methods at instantiation, because that relationship is still being defined.

Trying to resolve this issue has clarified the answer to this question. It seems like the problem is that Board isn't a real subclass of Matrix. That relationship is not set until the code actually executes. What is the JavaScript-esque way of handling this relationship?

1
  • 1
    Board.prototype = Matrix.prototype; is a bad idea. You want Board.prototype = Object.create(Matrix.prototype); (with a shim if necessary for the relevant subset of Object.create's functionality). Commented Feb 10, 2014 at 18:19

2 Answers 2

2

But the problem is that Board does not have access to Matrix's methods at instantiation, because that relationship is still being defined.

No. When you use the new operator on Board, then first the relationship ("prototype chain") will be defined and after that the Board constructor function will be called on the new instance, where it can call the Matrix function on the instance or add instance properties like .state. You can use the prototypically inherited set method without any problems in there.

Looking at Why is inheritance only defined at compile-time?

In JavaScript, inheritance is set up at runtime. You can declare the function body (using inherited methods in it), then set the prototype, then instantiate objects.

Board.prototype = Matrix.prototype;

Don't do that. You want Board.prototype = Object.create(Matrix.prototype).

Sign up to request clarification or add additional context in comments.

8 Comments

I'm not seeing the reason for the downvotes on this, Bergi's quite correct about what happens when you actually try to use the Board constructor.
I don't think this answer deserves downvotes. I assume that "...the constructor will be called on the new instance" refers to the Matrix constructor.
@cookiemonster: I did refer to the Board constructor, actually. It does call Matrix, sure.
Certainly you're not saying: "When you call new Board, then first the relationship ("prototype chain") will be defined and after that the Board constructor will be called on the new instance." I assumed you were referring to Matrix.
@cookiemonster: Yes, that's what I'm saying. You might want to read the linked docs about how the new operator works :-)
|
2

This is incorrect:

Board.prototype = Matrix.prototype;

Do this instead so that additions to Board.prototype don't affect Matrix.prototype.

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

Now Board.prototype is an empty object that inherits from Matrix.prototype.


I see no reason why your object created from Board won't have access to methods from Matrix.prototype, so I'd assume that you were perhaps overwriting or shadowing the Matrix.prototype methods.

The // etc. part of your code is likely the issue.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.