views:

380

answers:

10

There are two ways (that I know of) to create a JavaScript object. Which way do you prefer and why?

/* METHOD 1 */
function Foo() {
    this.Bar = function() {
        alert("FooBar");
    }    
}

/* METHOD 2 */
function Foo() {
}

Foo.prototype.Bar = function() {
    alert("FooBar");
}

I use the first method when I create my own objects because I find that it encapsulates the logic in a more readable fashion.

A: 

I prefer the first method, because it seems cleaner to me.

If I am using a library, though, like prototype, I will use its conventions.

pkaeding
+2  A: 

Method 1 is great when you have complete control of the module, but in some cases you need to use Method 2 when you are extending standard classes or someone else's class.

So, I prefer Method 1 for my own code but have to resort to Method 2 in some cases.

Joe Skora
+1  A: 

If you are going to have lots of little foos running around, #2 is your best option. Just take each instance at the point you need it and determine which is the best.

neouser99
+1  A: 

Method 1 is preferable since it limits access to the method so that it can only be called via Foo. If the Foo function depends on this, you definatly don't want it to be accessible outside the class which it is in method 2.

Method 2 primarily exists so you can extend classes to which you don't have access, but Method 1 should be preferred in all classes that you yourself write.

Orion Adrian
Method 1 does not hide the method because the syntax being used is "this.Bar =". In order to hide the method, you would need to do "var Bar =".
17 of 26
My phrasing was unclear. It has been corrected.
Orion Adrian
+12  A: 

Those two bits of syntax do two different things and which one you do will depend on how you are using the member functions.

In the first case, you get a copy of the Bar() code for every Foo object you create.

In the second case, you get one copy of Bar() for all Foo objects you create. This will give you a reduced memory footprint.

You always want to use the second method unless you want Foo to have private data, in which case it's required that Bar() be declared by the first method.

Private data example:

function Foo()
{
    var myPrivateVar;       // Only visible inside Foo()

    this.Bar = function()   // Visible to all
    {
        myPrivateVar = "I can set this here!";
    }
}
17 of 26
+4  A: 

With method 1 you create a bunch of closures for each instance. And they eat up memory.

Alisey
Excellent point. Especially important if you are dealing with a large number of relatively small objects, and the overhead starts to add up.
Shog9
Memory exists to be used - unless you are literally eating up hundreds of megs, I don't see this being a problem...
Jason Bunting
@Jason: out of curiosity, i tested this. Using the OP's two examples and a fresh browser instance, i created one million instances of each. The first method was between 3 and 5 times "heavier" depending on the browser, with Chrome killing the first test and IE6 grabbing almost 900MB.
Shog9
Interesting - so under 1K for each instance (in IE6) huh? That's not a huge amount, and who creates one million instances of anything? Personally, I feel the benefits gained building objects without modifying the prototype far outweigh the relatively minor 'extra' memory used...thanks for the info!
Jason Bunting
I ran the test myself with IE7 and FF3 on WinXP and it was amazing how much memory IE used and how long it took to instantiate the objects (regardless of how they were constructed) compared to FF3 - FF3 was blazing fast. Too bad Chrome kills the script, that was disappointing!
Jason Bunting
Yeah, IE is the most shocking example. As i mentioned, this is probably most concerning if you are using lots of instances - and you don't need anywhere near 1M objects to start running into problems: each method adds a closure, and each local var gets caught in the closure and adds to the overhead.
Shog9
+1  A: 

Method 2 is useful if you are trying to do something like:

Foo.prototype.onlyNeedsEvaluatingOnce = function() { return "Bar"; }();
Joshua
+1  A: 

i find use of prototype a bit hard er. but proptype helps you to implements hierarchy from object in an easy way:

function Person(lastName,firstName) { this.init(lastName,firstName) }

Person.prototype.init = function (lastName,firstName)
{
   this.lastName = lastName;
   this.firstName = firstName;
}

Employee.prototype = new Person();
function Employee(lastName,firstName,empID)
{
  this.init(lastName,firstName); 
}
var emp = new Employee('smith','john',1);
alert(emp.lastName);

certainly, you can implements hierachy also without prototype, but with prototype its' quite simple.

stefano m
+3  A: 

There are a couple of minor variations on method #2 that you might find helpful. Both work by initializing the prototype with an object literal, with the latter building the object literal in an anonymous function to allow for the creation of (static) private data in the resulting closure:

/* METHOD 2.1 */
function Foo21() {}

Foo21.prototype = 
{
   Bar : function() 
   {
      alert("FooBar");
   }
};

/* METHOD 2.2 */
function Foo22() {}

Foo22.prototype = (function() 
{
   return 
   {
      Bar : function() 
      {
         alert("FooBar");
      }
   };
})();
Shog9
+1  A: 

I find this form useful at times:

function returnObject()
{
    var privateVar = "Hello Private!";

    return {
        publicVar: "Hello Public!",
        publicPrivateVar: privateVar,

        getPrivateVar: function ()
        {
            return privateVar;
        },

        getPublicVar: function ()
        {
            return this.publicVar;
        }
    };
}


var o = returnObject();

alert(o.getPrivateVar() + " and " + o.publicPrivateVar);
roosteronacid