panosru
panosru

Reputation: 2959

Most optimized way to create JS Object

I'm looking for the most optimized way to have an object in JS; since JS allows you to do something in multiple ways I want to know which is considered to be "best practice".

A conceptual use of the object would be this:

var John = new Person('John');
var Foo = new Person('Foo');

console.log(John.getName()); //Return 'John'
console.log(Foo.getName()); //Return 'Foo'
console.log(John.name); //undefined
console.log(Foo.name); //undefined

I have some examples here:

Example #1:

var Person = function (name) {
    this.getName = function () { return name; }
}

Here I actually have no properties; "name" cannot be changed or be read by public and getName method can be accessed public and invoke with local name variable. This actually meets my needs.

Example #2:

function Person (name) {
    this.getName = function () { return name; }
}

This has same behaviour as example #1. I'm just not sure about the difference between var method = function () {}; and function method() {}; from a functional and performance perspective.

Example #3:

var Person = function (name) {
    this.name = name;    
    Person.prototype.getName = function () { return this.name; }
}

Here I have name property which can be read/write by public and I also have a prototype getName method that can be accessed public.

Example #4:

var Person = function (name) {
    this.name = name;
    if (!Person._prototyped) {
        Person.prototype.getName = function () { return this.name; }
        Person._prototyped = true;
    }
}

Here I have what I had in example #3 with the difference that I make sure that prototype methods are set only once and only when required.

So the end question is, which of those you will suggest me to follow or if any of them then which way is the best practice?

Upvotes: 3

Views: 411

Answers (3)

Jaseem
Jaseem

Reputation: 2285

Works well on node.js. AFAIK, arguments are mutable. Closures will remember values. Hence this will work. I guess this solves it all.

var Person = function(Name) {
    this.getName = function(){return Name;}
    this.setName = function(newName)  { Name = newName; }
},

me  = new Person('John');
console.log(me.getName());
me.setName('Peter');
console.log(me.getName());

Upvotes: 0

qwertymk
qwertymk

Reputation: 35276

In example 3 and 4 it should be:

var Person = function (name) {
    this.name = name;    
};
Person.prototype.getName = function () { return this.name; }

And:

var Person = function (name) {
    this.name = name;
};

if (!Person._prototyped) {
    Person.prototype.getName = function () { return this.name; }
    Person._prototyped = true;
}

As you don't need to mess with the prototype each time you call the constructor.

Not sure which is fastest (as they are all valid for your purposes), which is what your asking, but I wouldn't worry as this seems like micro-optimizing. If you must know then you can use a site like http://jsperf.com/

The fastest way I can imagine would be :

function Person(name) {
    this.getName = function() {
        return name;
    };
}

As minitech said. The reason is as follows:

Each time the js engine has to go "up" the prototype chain it takes away a fraction of a ms (or fraction of a sec on IE :) ), and as declaring variables can take up time (also negligible) you avoid doing that too. Hope that helps

Upvotes: 2

Ry-
Ry-

Reputation: 224904

For what you want, the best way is probably this:

/**
 * @constructor
 */
function Person(name) {
    this.getName = function() {
        return name;
    };
}

Why is this? Well, first of all, encapsulation. If possible, you generally want to put the function in the prototype, like so:

/**
 * @constructor
 */
function Person(name) {
    this.name = name;
}

Person.prototype.getName = function() {
    return this.name;
};

However! In this case, it appears you don't want Person.name to be accessible. For that reason, you need to use closures.

As for this method:

var Person = function (name) {
    this.name = name;    
    Person.prototype.getName = function () { return this.name; }
}

That's not good. You publicly expose this.name, so it offers no advantage over the previous prototype method, but you continually overwrite Person.prototype.getName with the same function. There's no point in doing that; this will be the appropriate object every time. What's more, Person.prototype.getName won't be accessible until the first Person object is instantiated so there's not much point in making it "public" in the first place. Your fourth example is basically identical, with more cruft making it harder to understand, but it still has all the disadvantages.

So, in this case, go with the first version; when possible, though, set methods on prototype so they can be called outside of an instance.

Finally, I would recommend using:

function Person() {
}

over

var Person = function() {
}

because 1) The second example is missing a semicolon, 2) the var implies that the constructor is variable which it should not be, and 3) I don't believe JDoc allows @constructor to be applied to it, causing a warning in Closure Compiler at least1.


1 Okay, not so important. But still...

Upvotes: 3

Related Questions