1

So when I make a library, I usually do it in this fashion:

var myLib = (function() {
    return {
        publicProperty: 'test',
        publicMethod: function() {
            console.log('public function');
        },
        anotherMethod: function() { //... },
        // .. many more public methods
    };
}());

I had overheard that creating libraries is faster and/or uses less memory for initialization if you write it like this:

var MyLib = function() {
   this.publicProperty = 'test';
};

MyLib.prototype = {
    publicMethod: function() {
        console.log('public method');
    },
    anotherMethod: function() { //... },
    // ... many more public methods
};

myLib = new MyLib();

Does one initialize faster than the other? Does my question even make sense? I assume that these accomplish the same task (that task being I go and use myLib.publicMethod() somewhere else in my code on docready). Thanks!

wattostudios
  • 8,666
  • 13
  • 43
  • 57
tester
  • 22,441
  • 25
  • 88
  • 128

2 Answers2

2

The two scripts produce different results.

In the first you create the object myLib with three (or more) properties. Its prototype is Object.prototype. The point is you have made one object.

In the second you create a global variable called publicProperty. This is probably not what you wanted. (EDIT: OP Question Corrected, this is no longer an issue.)

Still, assuming you meant to create an object with methods in the prototype, your code is probably slower on a naive JavaScript engine because calling methods in the prototype requires a traversal of the link from the object to the prototype.

Now if your intent is not to make a single but to make many instances of myLib then you will save a lot of memory by putting methods in the prototype, because you will have one copy of each function. You don't want thousands of copies of methods. :)

EDIT TO ADDRESS OP QUESTION:

Regarding the two approaches and how to make the first one "faster":

Theoretically you have a space-time tradeoff. By putting the methods directly in the object you don't have the prototype chain lookup. But the downside is that every instance has its own copy of the methods. If you are making multiple instances, you should define each of the methods once and place them in a prototype. Modern (V8-class) JavaScript engines are pretty good with this kind of stuff, so you should not be looking for optimize speed by packing methods into the object. Now, for singletons, go ahead and fill up the object. Another approach is to put all the methods in myLib itself, and create instances with Object.create(myLib). This makes myLib itself be the prototype for all the "instances" and is generally considered good form (at least if you follow the "Good Parts" suggestions, which I generally do).

Ray Toal
  • 86,166
  • 18
  • 182
  • 232
  • ah okay. so in your final paragraph, you describe what i'm trying to optimize. In my first example, I create a ton of public methods. How can I rewrite the first example to be faster? – tester Jul 23 '11 at 04:49
2

Edit: Looking at the changes on the question, I ask you:

  • Do you plan to have multiple "instances" of your library simultaneously?

If you don't, I don't see any benefit of using a constructor, you will have only one object, there's no point to define the properties on its prototype -they will be defined and used on a single object anyway-.

Using inheritance will be useful in the case you want to have multiple object instances, the methods will be shared, -reused and declared only once- higher in the prototype chain.


There are several issues in your second example:

var myLib = (function() {
   this.publicProperty = 'this';
}());

The myLib variable will contain just undefined -you are not returning anything from the function expression-, and your publicProperty will be defined as a property of the global object, since in the way you are executing this function, this will be bound to the global object.

Also, if the code is executed within strict mode, the this value in that case will be undefined, and your property access expression will just throw a TypeError -a good thing IMO, since I'm pretty sure you don't want to declare publicProperty as a member of the global object-.

myLib.prototype = {
    publicMethod: function() {
        console.log('public method');
    },
    anotherMethod: function() { //... },
    // ... many more public methods
};

Accessing the prototype property here will fail -remember, myLib is undefined-.

The prototype is only meaningful for functions, used on constructor functions -functions that are intended to be used with the new operator-, I think you are confusing that property with the internal [[Prototype]] property that all objects have.

Defining a property named prototype on a non-function object, will have no effect.

See also:

Community
  • 1
  • 1
Christian C. Salvadó
  • 807,428
  • 183
  • 922
  • 838