1

I'm having an issue with following code.console.log is working fine in logName method but not giving desired output in logNameAgain method. I tried to google but in vain. Could someone please explain what is going on here?

var testObj = {
    name: "This is test object",
    logName: function() {
        console.log(this.name);  //Works fine 

        function logNameAgain() {
            console.log(this.name); //Not giving expected result;
        }

        logNameAgain();

    }
};

testObj.logName();

jsfiddle

Seems like console.log in logNameAgain method pointing to window. It doesn't really make any sense to me?

Update: I understand that this can be fixed by using bind/call or self but I don't understand why this is happening?

JS-JMS-WEB
  • 2,555
  • 3
  • 17
  • 26
  • Hint: you are not passing `this` in any way to the call. Either qualify the call with an object or bind this with `bind`. – Wiktor Zychla Jun 10 '15 at 15:32
  • In response to your update, the duplicate I linked to begins with an explanation of why this is happening, in the very first section entitled "What you should know about `this`". If you are interested in further explanation, please give more information about what you don't understand about that explanation. – apsillers Jun 10 '15 at 15:35

1 Answers1

1

Try using .bind() (see the working jsfiddle):

var testObj = {
    name: "This is test object",
    logName: function() {
        console.log(this.name);

        var logNameAgain = function() {
            console.log(this.name);
        }.bind(this);

        logNameAgain();

    }
};

testObj.logName();

The problem was that the new function inside of logName has the window (global) context. All that means is that you need to somehow pass in the local context. Function.prototype.bind does just that.

If browser support is a concern, you can also do this hacky thing:

var testObj = {
    name: "This is test object",
    logName: function() {
        var that = this;
        console.log(this.name);

        var logNameAgain = function() {
            console.log(that.name);
        };

        logNameAgain();

    }
};

testObj.logName();

That's only if you need to support IE8 and below. Here's the compat table for .bind() (courtesy of MDN:

bind

Josh Beam
  • 19,292
  • 3
  • 45
  • 68