0

I have a question related to JavaScript object initializer notation. I am a bit surprised that the top example works since it's referring to the name of the instance in the definition. Are the two approaches identical? I have typically used the second approach, but they seem to achieve the same thing.

var myObj = 
{
   Message:"Test",
   someMethod:function(){
      $.get("/someUrl",function(){
        myObj.Message = "Returned Value";
      })
   }
}

var myObj = 
{
   Message:"Test",
   someMethod:function(){
      var that = this; //have to capture this in order to use it in a different context.
      $.get("/someUrl",function(){
        that.Message = "Returned Value";
      })
   }
}

I guess the top approach has advantages since you don't have to keep track of the current meaning of this since it may change in different contexts. Are there other differences?

Edit: Understand that the top approach is not always a recommended approach, but I guess I still see some advantages in certain cases. One such case is KnockoutJS where the binding parsing will redefine the meaning of this in bound click handlers on the view model. More here: http://www.appliness.com/10-things-to-know-about-knockout-js-on-day-one/.

In this case I would have to manually do some bookkeeping of the current meaning of this

I typically use the second approach, but I was just trying to fully understand the difference and why it even works :-). Definitely understand that it's only workable in a single instance scenario though.

TGH
  • 38,769
  • 12
  • 102
  • 135
  • exact duplicate of [Javascript: Object Literal reference in own key's function instead of 'this'](http://stackoverflow.com/questions/10711064/javascript-object-literal-reference-in-own-keys-function-instead-of-this) – Bergi Oct 16 '13 at 08:01

2 Answers2

1

this is set by the JS interpreter according to how something is called. It is very useful (and basically required) when you have multiple instances of a type of object because this is the only to know which object to reference so your second code example would be recommended.

Any object method call like obj.method() will cause this to automatically be set to obj inside the method.

If you have a singleton (only one instance of an object), then you can certainly use the named variable if you want, but there is generally no need to use the name as this will work just fine if you code the access to the object's methods properly.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
1

JavaScript's closure semantics are a little interesting here. They will, in fact, capture the variable currently being assigned to, despite the fact that logic might indicate that the variable does not exist yet.

This is actually a result of JavaScript's variable hoisting. Before a variable can ever be assigned to, it must be declared. Therefore, even in a case where myObj is not in the global scope, it will still be captured by the function, since effectively, you're writing this:

var o = (function () {
    var myObj; // hoisted declaration
    myObj = {
        message: "test",
        someMethod: function () { alert(myObj.message); },
    };
    return myObj;
})();
o.someMethod(); // alerts 'test'

However, this will not always work. If you can force the variable you assign it to out of the closure's scope, the variable will indeed be undefined.

function createObj() {
    return {
        message: "test",
        someMethod: function () { alert(myObj.message); },
    };
}

var o = (function () {
    var myObj;
    myObj = createObj();
    return myObj;
})();
o.someMethod(); // error: myObj is not defined

So, while using the name might work sometimes, it's a much more fragile approach. If the name isn't captured, or if the variable's name is reused internally, it can break entirely. Using the name instead of using this can cause code to break when refactoring, even when simply moving code around, which can be a pain to debug if you don't realize where the problems are coming from.

Basically, while the first method might work sometimes, it is not a general solution and provides no major advantages over just using this, so it is preferred to use this instead.

Community
  • 1
  • 1
Alexis King
  • 43,109
  • 15
  • 131
  • 205
  • I guess I was thinking abut the case where you have to do some book keeping of what the this reference is currently representing. I commonly the that = this assignment, but I guess with the named instance it's not needed in some cases – TGH Oct 16 '13 at 05:59
  • @TGH Ah, I see. I added a bit about why you should avoid using the name directly. It might work sometimes, but it's not worth the trouble. – Alexis King Oct 16 '13 at 06:06
  • Yeah, I agree using this is probably the cleanest way. – TGH Oct 16 '13 at 06:20
  • The OP is not effectively writing the IEFE, because he refers only to `o` - not `myObj`. – Bergi Oct 16 '13 at 08:04
  • @Bergi I wrote that to illustrate that, even without `myObj` being in the global scope, it is still captured by the function's scope. – Alexis King Oct 16 '13 at 13:50