4

I was reading an article here:

http://javascriptweblog.wordpress.com/2010/03/16/five-ways-to-create-objects/

It tells about five ways of creating objects. But my question is one of his way (3) is:

myApp.Notepad = function(defaultFont) {
    var  that = {};
    that.writeable = true;
    that.font = defaultFont;
    that.setFont = function(theFont) {
        that.font = theFont;
    }
    return that;
}

myApp.notepad1 =  myApp.Notepad('helvetica');

As per author, we can use it when multiple instances are needed we can use any pattern from 3 (above) to 5.

But as far as I know, we do need to use this keyword which reflects back newly created instances and refers to only that instance. However above, author uses that object instead of this and also there is no new keyword used above. How will it apply to multiple object instances ? Is it essentially same as using this?

GFoley83
  • 3,439
  • 2
  • 33
  • 46
Dev555
  • 2,128
  • 4
  • 30
  • 40

2 Answers2

4

In your example, that is a new object created by this line:

var that = {};

The function then proceeds to set the properties of this object.

On the other hand, this is used with a constructor function -- when called using new, a new object is automatically created and passed to the function as this. The same example could be written as:

myApp.Notepad = function(defaultFont) {
    this.writeable = true;
    this.font = defaultFont;
    this.setFont = function(theFont) {
        this.font = theFont;
    }
}

myApp.notepad1 = new myApp.Notepad('helvetica');
casablanca
  • 69,683
  • 7
  • 133
  • 150
  • Thanks I know but what is advantage of using `that` object instead of using `this` constructor method? – Dev555 Feb 21 '12 at 05:49
  • 1
    @Dev555 - it's just a different (round about) way to "construct" an object. I don't know if there's an advantage to it, but a subtlety is that the `setFont` function uses a closure, instead of referring to the `this` object. `setFont` uses `that` which is defined outside of it. Syntactically, it's slightly less clear about what it's doing since it side-steps the `new` operator. – Seth Feb 21 '12 at 06:05
  • @Seth: That's what is confusion, waiting to see if things get clarified. Thanks – Dev555 Feb 21 '12 at 06:10
  • @Dev555: Seth has got the differences down for you. Also, the constructor method sets the prototype of the new object and allows prototype chaining, which is not possible with the `that` method. I don't really see any advantage of using the `that` method. – casablanca Feb 21 '12 at 06:18
  • @Seth: well one major difference is that it would fail a `instanceof myApp.Notepad` check – qwertymk Feb 21 '12 at 06:20
  • 3
    Using a closure to reference an instance has a few issues. It's not very memory efficient since the scope chain when the object was created must be retained rather than being garbage collected. Also means methods can't be generic, calling them with some other value for *this* will operate on the original object, not the one passed to the function's *this*. Lastly, the name *that* doesn't give any hint as to what it actually is. I think it's much better to use *this* to refer to an instance and keep closures for cases where they are more efficient than alternatives. – RobG Feb 21 '12 at 06:35
  • 1
    I think these comments conclude that we should go with constructor pattern instead. – Dev555 Feb 21 '12 at 06:59
2

One advantage of the using the object literal constructor (your code) that hasn't been pointed out yet is that when you are creating a new instance of an object, the new keyword is not necessary. Or in other words, if you simply forget to use the new keyword, your code will still run as intended as you are no longer relying on the use of the new keyword to give the scope of this to your newly created object in your constructor function; The that object is now taking care of the scope for you.

This is the approach that the YUI library (and Douglas Crockford) takes for constructors.

Consider the following simple constructor:

var Car = function(model){
  this.model = model;
};

If you were to call Car('Dodge Viper'); or even var MyCar = Car('Dodge Viper');, the this in the function would actually refer to the global window object. So now the property Model above is actually a global variable, which is probably not what was intended.

var Car = function(model) {
  var that = {};
  that.model = model;
  return that;
};

// Both work the same.
var MamsCar = new Car("Mini Cooper"); // with 'new'
var DadsCar = Car("Bugatti Veyron"); // without 'new'
alert("Mam's car is a " + MamsCar.model + " and dad's car is a " + DadsCar.model);
GFoley83
  • 3,439
  • 2
  • 33
  • 46