Chris Middleton
Chris Middleton

Reputation: 5934

Is there any difference between these three ways of declaring methods in JS?

Say I have a type called MyObject and I want to add the method myMethod to it. Is there any difference (logically, but also performance-wise) between the following ways?

#1

function MyObject() {
    ...
}

MyObject.prototype.myMethod = function() {
   ...
};

#2

function MyObject() {
    this.myMethod = function() {
        ...
    };
    ...
}

#3

function MyObject() {
    this.myMethod = myMethod;
    ...
}

function myMethod() {
    ...
}

I wouldn't mind knowing if there's a performance difference - e.g. if way #2 is costly because it defines the function separately every time an object is instantiated - but I'm mostly concerned with whether the results are equivalent.

In addition, with method #2, isn't this the same way that a class-level/static method would be defined, so does it have the danger of being called like MyObject.myMethod();? If myMethod used this and it was called on MyObject rather than an instance of MyObject, I would think this would cause issues. So does the compiler/interpreter check to see whether this is present or would it throw an error?

Upvotes: 1

Views: 46

Answers (2)

Anthony
Anthony

Reputation: 2411

Option 1: You can call my method without instantiating MyObject:

MyObject.prototype.myMethod();

Options 2: You must instantiate the MyObject to be able to access myMethod.

This will fail:

MyObject2.myMethod();
Uncaught TypeError: undefined is not a function

This will not:

var myObject = new MyObject2();
myObject.myMethod();

Check out the code pen: http://codepen.io/sessa/pen/tfqln

Upvotes: 2

Mike Cluck
Mike Cluck

Reputation: 32511

#1: This is the preferred way to write "class-level" methods. This saves on memory (as you'll see in #2) and JS engines can know that each instance will have this method and optimize around that.

#2: You're right, this one is more costly because it creates a new function for each instance. The difference here is that you can include private variables generated in the constructor. For example:

function MyObject() {
    var name = 'Me';
    this.getName = function() {
        return name;
    };
}

Only things created in the constructor will have access to name.

#3: This approach is largely the same as #1 but I imagine that JavaScript engines are not written to optimize for this case (but this might not be true and may change, JS engines are constantly evolving). This also creates a global function (assuming you're not using a module system) which can create major issues later.

Upvotes: 2

Related Questions