Search code examples
javascriptprototypal-inheritance

Javascript Prototype: Replacement vs Addition


I'm working with a fairly simple Point2D data structure I built to be inheritable for say a Point3D in the future and I've followed all the guides and similar questions I can find, but none seem help with my issue.

I've defined Point2D as follows:

function Point2D (px, py)
{
  this.x = px;
  this.y = py;

  Point2D.prototype =
  {
    constructor: Point2D,

    move:function (mx, my)
    {
      this.x = mx;
      this.y = my;
    },
    translate:function (dx, dy)
    {
      this.x += dx;
      this.y += dy;
    }
  };
};

I instantiate the object as follows:

var p2d1 = new Point2D(2,3);

Then I call one of the methods as follows:

p2d1.move(1,2);

And the result is:

TypeError: Object #<Point2D> has no method 'move'

I have not idea why my methods don't resolve.

I've messed around with it for a good while and found that I can declare Point2D methods this way and they will work.

Point2D.prototype.move = function () {};

Can anyone explain why they first style of replacing the entire prototype does not work, but adding functions to the existing prototype does work?


Solution

  • When you call new Point() the first time, Point.prototype is still an "empty" prototype. I.e. the instance that is created doesn't inherit any methods.

    You change (replace) the prototype after the instance was already created. JavaScript has assign by value, not assign by reference. Quick example:

    var a = 5;
    var b = {c: a};
    a = 10;
    

    b.c is still 5, since assigning to a doesn't change what b.c refers to.

    Point2D.prototype.move = function () {};
    

    works because you are not replacing Point2D.prototype, you are simply mutating the existing object.

    Overall, assignments to *.prototype should take place outside the constructor:

    function Point2D (px, py) {
      this.x = px;
      this.y = py;
    };
    
    Point2D.prototype = { };