1

As we know , setTimeout is not working correctly with this becuase it runs in a global scope ( and this will be window)

But I've made a simple test :

Just wrap it with function :

var o={}
o.a=1;
o.m=function (){alert(this.a);}


setTimeout( 
  function (){
               o.m()  ;
             }

    ,100);

And it does alert 1.

Am I missing something here ? why none of the answer suggests this solution ? does it behave different ?

p.s. : for those who intereseted here is a demo where it fails :

var o={}
o.a=1;
o.m=function (){alert(this.a);}


setTimeout( o.m   ,100); //undefined
Royi Namir
  • 144,742
  • 138
  • 468
  • 792

3 Answers3

3

The proper way to do this is to bind() the scope of the anonymous function.

var o = {};
o.a = 1;

setTimeout(function (){
    alert(this.a);
}.bind(o), 1000);

While your answer produces the same results, it's not accessing the scope of o from within the anonymous function. It's merely calling a function of the global object o.

Your reference to this.a is from within the scope of o.

Steven Moseley
  • 15,871
  • 4
  • 39
  • 50
  • I know. but myne is working also.why is doesnt being mentioned anywhere ? – Royi Namir Jun 17 '13 at 10:38
  • Yours is not referencing the scope of o from within the anonymous function. It's merely calling a method of the global object `o` – Steven Moseley Jun 17 '13 at 10:40
  • mmmm so X.method() will always consider [this] as X.... while using `this` without "object holder" should be used with bind.call.apply etc.....right ? – Royi Namir Jun 17 '13 at 10:43
  • Yes. `this` references the scope of the method. In the case of `X.method()`, `this` references `X`. – Steven Moseley Jun 17 '13 at 10:44
  • Well i thought that even in pattern of `X.method` , `this` will refer to the global. and _that_ was my mistake. thank you. – Royi Namir Jun 17 '13 at 10:45
1

You're missing closures. Your callback function will have access to o, even if it's not been declared globally, as long as the callback was defined in a scope that did have access to o.

JS can't GC o, because the callback function still references it, hence your snippet works

Example:

(function()
{
    var scope = {};//an empty object
    setTimeout(function()
    {
        console.log(scope);
        console.log(typeof scope);
    },1000);
}());
console.log(scope);

Here, you'll see undefined being logged, and (about) a second later, you'll see {} followed by object appear.
Whereas:

var foo = {bar: 'foobar',
           callback: function()
           {
               console.log(this);
           }
};
setTimeout(foo.callback, 1000);
console.log(foo.callback());

Will first log the object, referenced by foo, but then a second later, the same function object will log the global object because (as you say correctly), the function reference is invoked in the global context. The only way to avoid this is to use bind, or create another closure (but that would take us too far ATM).

I have gone into more detail on JS's ad-hoc context binding and reference resolving here, here, here, here and so on, and so forth

Community
  • 1
  • 1
Elias Van Ootegem
  • 74,482
  • 9
  • 111
  • 149
0

"this" is defined differently in different scopes, whereas you only defined "o" globally.

LouD
  • 3,776
  • 4
  • 19
  • 17