2

undefined undefined当我定义并调用函数时,我得到setTimeout如下:

var person = {
    first: 'joe',
    last: 'doe',
    getName: function(){
        console.log(this.first + ' ' + this.last);
    }
}

setTimeout(person.getName(), 2000);

除非我将其包装person.getName()在一个函数中,如下所示:

setTimeout(function(){
    person.getName()
}, 2000);

现在我得到了正确的输出。为什么会这样?

4

6 回答 6

3

假设您的意思是:

var person = {
    first: 'joe',
    last: 'doe',
    getName: function(){
        console.log(this.first + ' ' + this.last);
    }
}

setTimeout(person.getName, 2000);

您未定义的原因是您实际上正在做的是:

var somefunc = person.getName; 
setTimeout(somefunc, 2000);

所以 somefunc 在 window 的上下文中被调用。即window.somefunc()

但是,当您这样做时

setTimeout(function(){
    person.getName()
}, 2000);

getName 的上下文在您调用(而不是传递)person.getName 时被保留

于 2013-05-30T01:21:15.353 回答
1

我刚刚在这里回答了类似的问题:

如何将参数传递给 setTimeout() 回调?

setTimeout 函数将上下文固定到窗口,所以不可能做你想做的事!

为此,我将 setTimeout 函数包装在另一个可以设置上下文的函数中:

myNass_setTimeOut = function (fn , _time , params , ctxt ){
return setTimeout((function(_deepFunction ,_deepData, _deepCtxt){
            var _deepResultFunction = function _deepResultFunction(){
                //_deepFunction(_deepData);
                _deepFunction.apply(  _deepCtxt , _deepData);
            };
        return _deepResultFunction;
    })(fn , params , ctxt)
, _time) 
};

// lets try this functions :
for(var i=0; i<10; i++){
   setTimeout(function(){console.log(i)} ,1000 ); // stock setTiemout in closure
}

for(var i=0; i<10; i++){
   setTimeout( console.log(i) ,1000 ); // stock setTiemout direct call 
}

for(var i=0; i<10; i++){
   setTimeout(console.log ,1000 , i); // stock setTiemout not compatible IE
}

for(var i=0; i<10; i++){
   myNass_setTimeOut(console.log ,1000 , [i] , console); // wrapped setTimeout
}

所以回答你的问题:

var person = {
    first: 'joe',
    last: 'doe',
    getName: function(){
        console.log(this.first + ' ' + this.last);
    }
}

setTimeout(person.getName(), 2000);

当您启动时:setTimeout(person.getName(), 2000);setTimeout 将在未来 2 秒(2000 毫秒)内执行第一个参数!

但是你的第一个论点的价值是什么?: 你的函数 person.getName 的结果( ),所以它相当于:

var _arg1 = person.getName();
setTimeout(_arg1 , 2000);

这是非常不同的:

var _arg1 = person.getName;
setTimeout(_arg1 , 2000);

第一种情况是将函数的结果传递给 setTimeout 等待对函数的引用。在第二种情况下,您传递对函数的引用(很好,这是预期的),但不是在良好的上下文中!

所以,现在你必须修复上下文:核心 javascript 函数:应用

现在试试这个:

var _arg1 = function(){ person.getName.apply(person) };
setTimeout(_arg1 , 2000);
myNass_setTimeOut(person.getName , 2000 , null , person);

所以你有两个选择:

  • 修复传递给 setTimeout 的每个参数的上下文。
  • 使用为你做的功能

myNass_setTimeOut 函数会成功的!

现在,让我们看一些更深入的东西:

var person = {
        first: 'joe',
        last: 'doe',
        getName: function(){
            console.log(this.first + ' ' + this.last);
        } ,
        say : function(sentence){
             console.log(this.first + ' ' + this.last + ' say : ' + sentence)
        }
    }

如何将参数语句传递给 setTimeout ?

var heSay = "hello !"; setTimeout(person.say(heSay) , 1000 ); heSay = "goodBye !";
// not good : execute immediatly

var heSay = "hello !";setTimeout(function(){person.say(heSay)} , 1000 ); heSay = "goodBye !";
// not good : hesay googbye

var heSay = "hello !"; setTimeout(person.say , 1000 , heSay); heSay = "goodBye !";
// not good bad context

var heSay = "hello !"; setTimeout(function(whatHeSay){person.say(whatHeSay)} , 1000 , heSay);heSay = "goodBye !";
// GOOD ! ok but not compatible with IE

var heSay = "hello !"; myNass_setTimeOut(person.say , 1000 , [heSay] , person ); heSay = "goodBye !";
// just good !

希望这对你有帮助!

编辑 :

对于现代浏览器支持绑定,请不要关心 这里所说的@dandavis

于 2013-05-30T07:44:39.597 回答
0
  1. 你说得太早了。
  2. 当您保存没有附加对象的函数 ref 时, this 会被破坏。

解决方案?

使用 bind 并且不要提前调用它:

var person = {
    first: 'joe',
    last: 'doe',
    getName: function(){
        console.log(this.first + ' ' + this.last);
    }
}

setTimeout(person.getName.bind(person), 2000);
于 2013-05-30T01:08:25.033 回答
0

您的第一个功能对我来说很好(在 Chrome 中测试):

http://jsfiddle.net/fzrxK/1/

var person = {
    first: 'joe',
    last: 'doe',
    getName: function(){
        alert(this.first + ' ' + this.last);
    }
}

setTimeout(person.getName(), 2000);

也许其他地方还有另一个问题?

于 2013-05-30T01:10:07.517 回答
0

调用person.getName()执行函数并返回undefined(因为在该函数中没有声明要返回)。

你想要的是:

setTimeout(person.getName, 2000);

调用setTimeout(person.getName(), 2000);设置了一个超时时间来执行person.getName()which isundefined而不是函数返回的结果。

调用setTimeout(person.getName, 2000);设置了执行函数的超时时间person.getName

带括号执行函数。不带括号传递变量(恰好被定义为函数)。

编辑:正如@Isaac 指出的那样,传递函数person.getName也会改变行为,this所以这也可能不是你想要的。

于 2013-05-30T01:12:09.783 回答
0
var person = {
    first: 'joe',
    last: 'doe',
    getName: function(){
        console.log(this);
    }
}
person.getName()
setTimeout(person.getName, 2000);

输出:

Object {first: "joe", last: "doe", getName: function}
Window {top: Window, window: Window, location: Location, external: Object, chrome: Object…}

我的猜测是,JavaScript 将getName函数拉出person

于 2013-05-30T01:12:21.303 回答