1

When I use var keyword to declare any variable it gets declared inside the enclosing scope. However in the code below, I have declared function c (inside an object method a.b) with var keyword and still this inside the function c is bound to the global object window. Why is this?

var a = {
        b: function () {
            var c = function () {
                return this;
            };
            return c();
        }
    };

document.write(a.b());  //prints: [object Window]
Mahesha999
  • 22,693
  • 29
  • 116
  • 189
  • 2
    The `this` value depends on the *context of invocation*, not on the *scope of the variable holding the function.* – deceze Jun 16 '13 at 12:46

2 Answers2

3

The value of this is determined by context, not scope.

When you call a function without any context (context.func()) as you do there (c()), the default context is the default object (which is window in browsers) unless you are in strict mode (in which case it is undefined instead).

(There are exceptions to this rule, such as apply, call, bind, and new but none of them apply here).

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • Thanks, I got it. Just curious why [this](http://jsfiddle.net/Mahesha999/3td3D/1/embedded/js,result) JSFiddle prints `undefined` instead of `global`, though the same in browser works right – Mahesha999 Jun 16 '13 at 18:36
  • Because you configured JS Fiddle to wrap it in a function and use it as an onload handler: `window.onload=function(){ var context = "global";` – Quentin Jun 16 '13 at 18:58
1

Many people get confused by . The value depends on one of 4 methods of invocation.
However, functional invocation and cause most of the confusion.
If a function is a member of an object, is the object itself.

obj.someFunction(); //method invocation

If a function is called without context is the global object (in 'strict mode' is undefined.)

someFunction();  //functional invocation

The confusion occurs when a function is called within an object, but not as a member of the object as in anObject.testWithHelper(..);

var testForThis = function(isThis, message) {
    //this can be confusing
    if(this === isThis) 
        console.log("this is " + message);
    else
        console.log("this is NOT " + message);    
};  

//functional invocation
testForThis(this, "global"); //this is global

var anObject = {
    test: testForThis, //I am a method
    testWithHelper: function(isThis, message) {
        //functional invocation
        testForThis(isThis, message + " from helper");
    }
};

//method invocation
anObject.test(anObject, "anObject"); //this is anObject
//method invocation followed by functional invocation
anObject.testWithHelper(anObject, "an object"); //this is NOT anObject from helper

Here is my JSFIDDLE

If you would like c to return a, you can use :

var a = {
    b: function () {
        var that = this;
        var c = function () {
            return that;
        };
        return c();
    }
};

Or avoid this all together:

var getNewA = function() {
    var newA = {};
    newA.b = function() {
        var c = function() {
            return newA;
        };
        return c();
    };    
    return newA;
};

var newA = getNewA();
Mke Spa Guy
  • 793
  • 4
  • 13
  • Overly complicated code. Can simply be rewritten as: var a = { b: function () { var c = function () { return this; }; return c.call(this); } }; – Taha Ahmad Dec 19 '13 at 16:20