Skip to content Skip to sidebar Skip to footer

'this' Returning Either 'Object' Or 'Window' Inside The Same Object

Now that's a new one for me. I searched around but can't find the solution elsewhere. I've got this code (coffeescript) : PositionDetector = -> detectPosition : ->

Solution 1:

Question is, why does the first 'this' output 'Object' and the second one 'Window'?

this is set primarily by how a function is called (for now*), not where it's defined. In the first case, the way you're calling the function is through an object reference (positionDetector.detectPosition()), and so the JavaScript engine sets this to be the object you used as part of the expression making the call. In the second case, the function isn't being called as part of an expression retrieving the function reference from an object property, so this takes its default value (the global object in loose mode, undefined in strict mode). Here's a simpler example:

var obj = {
    foo: function() {
        console.log(this);
    }
};
var f = obj.foo;
obj.foo(); // `this` is `obj` during the call
f();       // `this` is not `obj` during the call

To solve it, you could use Function#bind to use a specific this value during the callback:

navigator.geolocation.getCurrentPosition(this.locationHandler.bind(this))

Function#bind creates a function that, when called, will call the original file with a specific this value (and any optional arguments you provide).

More about this (on my blog):


* "for now": ES6 introduces CoffeeScript-style arrow functions, which have a this value that's set by the context in which the function is created. That wouldn't really help you here, but it makes my usual "...is set primarily by how a function is called..."* statement no longer true. :-)


Solution 2:

Because this depends on the caller. The caller to this.locationHandler is navigator.geolocation.getCurrentPosition(callback) and it calls the function like callback(), notice, there is no dot in that call, meaning there is no value for this. The solution is to set this permanently using bind:

navigator.geolocation.getCurrentPosition(this.locationHandler.bind(this))

Remember, general rule: no dot, no this, unless you used call or apply to call the function, or bind to set the value of this forever.


Solution 3:

Both T.J. Crowder & elclanrs are right.

As a brief explanation: "this" refers to object context (A.K.A. scope) and it does not work exactly as you expected in javascript unfortunately ,

  • detectPosition() is called in the context of PositionDetector by you.
  • locationHandler() is called in the context of window which is the global object and the event originator.

IMHO this situation renders Javascript stupid. There are two methods to overcome this effect. First is the "bind" method as they have shown. The second one is the magical "closure" generation.


Post a Comment for "'this' Returning Either 'Object' Or 'Window' Inside The Same Object"