1

Im reading through the YDKJS books and I thought I understood lexical this for the most part.

However there is a section with code that shows this:

var obj = {
    id: "awesome",
    cool: function coolFn() {
        console.log( this.id );
    }
};

var id = "not awesome";

obj.cool(); // awesome

setTimeout( obj.cool, 100 ); // not awesome

Ok so the first obj.cool() makes sense of course....but why is the setTimeout printing not awesome.....I mean it's still calling obj.cool() which this refers to it's own objects id?

Or does setTimeout get called as another function that calls obj.cool()? but even in that case (Which I tried calling obj.cool() inside another function that also had an id property and it still printed the right one......so why would the this change with setTimeout?

msmith1114
  • 1,853
  • 3
  • 18
  • 60
  • Because `this` is pointing to `window` inside `setTimeout` and any variable defined outside function becomes a part of global scope – Rajesh May 17 '17 at 06:27
  • 4
    Read documentation first before asking https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout – dfsq May 17 '17 at 06:28
  • 'this' depends on the function invocation. calling it like obj.method() will set 'this' to be obj. whereas calling it like method() will set 'this' to the global scope More info here: https://rainsoft.io/gentle-explanation-of-this-in-javascript/ – derp May 17 '17 at 06:28
  • Each function has a *context* in which it is invoked. When you're invoking `obj.cool()` directly, the context (`this`) is indeed `obj`. But, when you're passing a reference to a function that happens to be assigned on `obj`, the context would be determined by the (well...) the context in which it is being executed, and in your case, `setTimeout` would invoke it in a global context, hence `this === window`. – haim770 May 17 '17 at 06:29
  • 2
    Uh, [`this` is **not** lexical](http://stackoverflow.com/q/3127429/1048572)? – Bergi May 17 '17 at 06:29
  • Here is a way around it but, you need to use a constructor to make objects so you cannot use literals: https://jsfiddle.net/85m3geob/1/ – Dellirium May 17 '17 at 06:38
  • As Rajesh mentioned, this is pointing to window object inside setTimeout. Do use bind method to bind the required object to the function, `setTimeout( obj.cool.bind(obj), 100 ); ` Learn function methods suchas `bind`, `call` and `apply` to understand what is happening http://javascriptissexy.com/javascript-apply-call-and-bind-methods-are-essential-for-javascript-professionals – Gopinath Shiva May 17 '17 at 06:40

1 Answers1

1

Since the OBJ.COOL function is passed by reference, you are not actually passing the context object with it. The function gets new invocation context and executes on the WINDOW object, which now has a property called ID which was defined earlier.

Martin Chaov
  • 685
  • 6
  • 14
  • Ah, so because it's being passed as a parameter it's not passing the context. But just calling it in global space keeps the context intact. – msmith1114 May 17 '17 at 17:12