4

I'm encountering with a little problem with the context of this :

In JavaScript this always refers to the "owner" of the function we're executing, or rather, to the object that a function is a method of.

So, this code :

var o={

  f:function ()
     {
       console.log(this); //the owner of the function is `o`
     }
}

console.log(o.f()) // this shows the `o` as this

all OK.

So why this code

var o = {
    f: function ()
    {
        return function ()
        {
            console.log(this);
        }
    }
}
console.log(o.f()())

Shows that this is the global object/window ?

o.f() returns a function , and then I execute it.but still the Hoster object is o. so why it shows the hoster as window?

gen_Eric
  • 223,194
  • 41
  • 299
  • 337
Royi Namir
  • 144,742
  • 138
  • 468
  • 792
  • 3
    The anonymous function you're returning is owned by what/who? No one...meaning `window`. You could always bind `this` to the returned function so that the value of `this` will always refer to `o`. Your last line is technically this: `console.log((function () { console.log(this); })());` – Ian Apr 17 '13 at 17:55
  • [here](http://stackoverflow.com/questions/111102/how-do-javascript-closures-work) you can find some great answers regarding how closures work that might help understand this – excentris Apr 17 '13 at 18:02
  • For a more detailed explanation of now `this` works in javascript see: http://stackoverflow.com/questions/13441307/how-does-the-this-keyword-in-javascript-act-within-an-object-literal/13441628#13441628 – slebetman Apr 17 '13 at 18:10

5 Answers5

4

The value of this is determined by the object you call the function through, not the place where the function is declared.

For example, if you did the following:

var f = o.f;
console.log(f());

you'd see that this is window as well.

You can also do stuff like this:

var o2 = { f: o.f };
console.log(o2.f());

There, this would be the o2 object, not o.

In your case, o.f is returning a function, which you're invoking without an object reference. In that case, the function invoked is called with this set to the global object (which in a browser is window).

If you want to preserve the this pointer, you'll need to capture it in a closure, like so:

var o = {
    f: function ()
    {
        var self = this;
        return function ()
        {
            console.log(self);
        }
    }
}
console.log(o.f()())

and then you'd have the right object reference regardless of how it's called.

Chris Tavares
  • 29,165
  • 4
  • 46
  • 63
2

No. The returned function is just a function, not hosted on any object (which makes this default to the global object). Think of that double-invocation as

var temp = o.f();
temp();

Instead of that "owner context" metapher (which fails too often), better refer to MDN's introduction to the this keyword. The "owner" object explanation only works for the case when you call a method on an object - as soon as you pass the function around (into a callback, returning it, assigning it) it looses its context.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
2

this is set by how the function is called, not by where it's stored.

o.f() works because you are calling f() in the context of o. If you were to copy that function to another object, this would change.

For example:

var x = {
  a: o.f
};

console.log(x.a()); // logs x, not o.  because the "context" is x

In your second example, o.f() returns a function, which is then ran with "no context". That makes the "context" set to window.

gen_Eric
  • 223,194
  • 41
  • 299
  • 337
1

The answer is simple. You are returning a closure and subsequently evaluating it in the scope of the window. If you didn't return the function, you wouldn't have this problem.

The solution:

var o = {
  f: function() {
    return function() { console.log(this); }
  }
};
console.log(o.f().apply(o, []));

Will transfer ownership of the closure to o from nothing (= window)

Sébastien Renauld
  • 19,203
  • 2
  • 46
  • 66
1

When a function has no owner, getting the local context falls back to the global context since the real context is undefined. And it does the same if the real context is null.

All that is true in non strict mode!

In strict mode, getting the local context does not fall back to anything else. The context stays as it is, that is to say in the case of a not owned function : undefined. And it's very important to be aware of it.

atondelier
  • 2,424
  • 15
  • 11