1

正如我们所知,setTimeout它不能正常工作,this因为它在全局范围内运行(并且this将会window

但我做了一个简单的测试

只需用函数包装它:

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


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

    ,100);

它确实会发出警报1

我在这里错过了什么吗?为什么没有一个答案表明这个解决方案?它的行为有什么不同吗?

ps:对于那些在这里感兴趣的人来说,这是一个失败的演示:

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


setTimeout( o.m   ,100); //undefined
4

3 回答 3

3

这样做的正确方法是bind()匿名函数的范围。

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

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

虽然您的答案产生了相同的结果,但它并没有o从匿名函数中访问范围。它只是调用全局对象的函数o

您的参考this.a来自o.

于 2013-06-17T10:38:09.660 回答
1

你错过了闭包。您的回调函数将有权访问o,即使它没有在全局范围内声明,只要回调是在确实有权访问的范围内定义的o

JS 不能 GC o,因为回调函数仍然引用它,因此您的代码段有效

例子:

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

在这里,您将看到undefined被记录,并且(大约)一秒钟后,您将看到{}随后object出现。
然而:

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

将首先记录由 引用的对象,foo但稍后,同一个函数对象将记录全局对象,因为(正如您所说的),函数引用是在全局上下文中调用的。避免这种情况的唯一方法是使用bind,或创建另一个闭包(但这会让我们走得太远 ATM)。

我已经详细介绍了 JS 的临时上下文绑定和引用解析herehereherehere等等,等等

于 2013-06-17T10:41:58.317 回答
0

“this”在不同范围内的定义不同,而您只在全局范围内定义了“o”。

于 2013-06-17T10:39:38.980 回答