1

I have to work on the following piece of code:

function Vector(x, y) {
    this.x = x || 0;
    this.y = y || 0;
}

Vector.add = function(a, b) {
    return new Vector(a.x + b.x, a.y + b.y);
};

Vector.sub = function(a, b) {
    return new Vector(a.x - b.x, a.y - b.y);
};

Vector.scale = function(v, s) {
    return v.clone().scale(s);
};

Vector.random = function() {
    return new Vector(
        Math.random() * 2 - 1,
        Math.random() * 2 - 1
    );
};

Vector.prototype = {
    set: function(x, y) {
        if (typeof x === 'object') {
            y = x.y;
            x = x.x;
        }
        this.x = x || 0;
        this.y = y || 0;
        return this;
    },

    add: function(v) {
        this.x += v.x;
        this.y += v.y;
        return this;
    },

    sub: function(v) {
        this.x -= v.x;
        this.y -= v.y;
        return this;
    },

    scale: function(s) {
        this.x *= s;
        this.y *= s;
        return this;
    },

    length: function() {
        return Math.sqrt(this.x * this.x + this.y * this.y);
    },

    lengthSq: function() {
        return this.x * this.x + this.y * this.y;
    },

    normalize: function() {
        var m = Math.sqrt(this.x * this.x + this.y * this.y);
        if (m) {
            this.x /= m;
            this.y /= m;
        }
        return this;
    },

    angle: function() {
        return Math.atan2(this.y, this.x);
    },

    angleTo: function(v) {
        var dx = v.x - this.x,
            dy = v.y - this.y;
        return Math.atan2(dy, dx);
    },

    distanceTo: function(v) {
        var dx = v.x - this.x,
            dy = v.y - this.y;
        return Math.sqrt(dx * dx + dy * dy);
    },

    distanceToSq: function(v) {
        var dx = v.x - this.x,
            dy = v.y - this.y;
        return dx * dx + dy * dy;
    },

    lerp: function(v, t) {
        this.x += (v.x - this.x) * t;
        this.y += (v.y - this.y) * t;
        return this;
    },

    clone: function() {
        return new Vector(this.x, this.y);
    },

    toString: function() {
        return '(x:' + this.x + ', y:' + this.y + ')';
    }
};

This piece of code has a function Vector and to this function there is a property attached which is Vector.add. However, a few lines down there is Vector.prototype which then in turn defines add.

So at this point we have Vector with Vector.add and Vector.prototype.add and I am not quite sure what is the difference when calling these.

For full reference the code I am trying to redo is from the Gravity Points CodePen so you can view the whole code as well as its usage.

However, to me, as someone who has mainly used ECMAScript 6, this code is looking very strange, to say the least.

Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
Pavlin Petkov
  • 1,022
  • 3
  • 17
  • 38
  • If function are attached to Vector.prototype, they are instance method. Otherwise, they're the equivalent of a static property – Axnyff Apr 30 '18 at 13:09

2 Answers2

1

This is a difference between a class level function and an instance function, meaning you should be able to use Vector.add without an instance, and the other with an instance.

yakubori
  • 49
  • 2
  • Please update this to be an answer. If not, please wait a few accepted answers until you have the 50 rep you need to make comments – mplungjan Apr 30 '18 at 13:13
  • I see....then this comes down to bad naming...as it is really confusing to understand what is going on....and the comments in chinese sure don't help much. Thanks! – Pavlin Petkov Apr 30 '18 at 13:16
1

For more info on static vs prototype methods, you can read this answer here. In your case though:

Static call returns a new Vector by adding two vectors together. v1 and v2 remain unchanged.

let v1 = new Vector(1, 1);
let v2 = new Vector(2, 2);
let v3 = Vector.add(v1, v2);

v1.toString(); // (x:1, y:1)
v2.toString(); // (x:2, y:2)
v3.toString(); // (x:3, y:3)

Prototype call adds two vectors together but does not create a new Vector; instead the x and y properties of v2 are added onto v1 in place.

let v1 = new Vector(1, 1);
let v2 = new Vector(2, 2);
v1.add(v2);

v1.toString(); // (x:3, y:3)
v2.toString(); // (x:2, y:2)

Note the prototype method returns a reference to the instance it was called on so subsequent calls can be chained:

v1.add(v2).sub(v3).add(v4).toString();
chazsolo
  • 7,873
  • 1
  • 20
  • 44