开发者

Should I use prototype or not?

I'm creating a Vector class, which can basically hold three numerical values. However, a lot of operations can be done on such a vector - e.g. getting the magnitude, adding or subtracting another vector etc.

I was wondering whether these functions should be coded as being a prototype function of the Vector class, or that I should define them in the constructor.

So which of these two methods is preferable?

function Vector3D(x, y, z) {
    this.x = 开发者_开发技巧x;
    this.y = y
    this.z = z;
}

Vector3D.prototype.magnitude = function() {
    return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
};

or

function Vector3D(x, y, z) {
    this.x = x;
    this.y = y;
    this.z = z;

    this.magnitude = function() {
        return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
    };
}


This is exactly the situation for using prototype. I see two main benefits for doing so:

  1. Functions are not created multiple times. If you define the functions inside the constructor, a new anonymous function is being created for each function you define, every time the constructor is called. Prototypes are static objects, and each instance of Vector3D will simply reference the prototype functions.
  2. The prototype is a single object that can be easily manipulated. This affords great flexibility; unfortunately I'm only able to provide a few examples of what this can offer:
    1. If you wanted to create a child class, for example Vector3DSpecial, you can simply clone Vector3D.prototype and assign this to Vector3DSpecial.prototype. While you can also do this using constructors by Vector3DSpecial.prototype = new Vector3D();, constructors may contain side-effects which will get executed in that simple prototype assignment, and therefore should be avoided. With prototypes, you may even choose only particular functions in the prototype to be copied over to the new class.
    2. Adding methods to Vector3D is simply a matter of adding properties to the prototype, and allows your code to be more easily split / organised into multiple files, or to allow for adding methods in other parts of the code dynamically. Sure, you can do a combination of adding methods in the constructor and via the prototype, but that is inconsistent and is likely to lead to more complexity further down the track.

When would I not use prototype? For singleton objects, for example a controller that interacts with a page and may delegate work off to other objects. A global "notification" object is one such example. Here, extending is unlikely, and the object is only created once, making the prototype an additional (conceptual) complexity.


Prototyped methods would only work for public properties, if you would keep track of x, y, z as "private" variables the prototype would not work.

I would use the latter, because you might want methods that only work with private/internal variables, but it all depends on context.

function Vector3D(x, y, z) {
   // x, y, z is automatically in this scope now, but as private members.
   this.magnitude = function() {
        return Math.sqrt(x * x + y * y + z *z);
   }
}


ECMA 6 http://es6-features.org/#BaseClassAccess

class Shape {
    …
    toString () {
        return `Shape(${this.id})`
    }
}
class Rectangle extends Shape {
    constructor (id, x, y, width, height) {
        super(id, x, y)
        …
    }
    toString () {
        return "Rectangle > " + super.toString()
    }
}
class Circle extends Shape {
    constructor (id, x, y, radius) {
        super(id, x, y)
        …
    }
    toString () {
        return "Circle > " + super.toString()
    }
}

ECMA 5

var Shape = function (id, x, y) {
    …
};
Shape.prototype.toString = function (x, y) {
    return "Shape(" + this.id + ")"
};
var Rectangle = function (id, x, y, width, height) {
    Shape.call(this, id, x, y);
    …
};
Rectangle.prototype.toString = function () {
    return "Rectangle > " + Shape.prototype.toString.call(this);
};
var Circle = function (id, x, y, radius) {
    Shape.call(this, id, x, y);
    …
};
Circle.prototype.toString = function () {
    return "Circle > " + Shape.prototype.toString.call(this);
};
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜