2013-05-30 104 views
2

我得到undefined undefined當我定義和調用setTimeout功能如下:JavaScript函數封裝

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); 

現在我已經獲得正確的輸出。爲什麼這樣?

+0

你調用settimout函數初始化人 – Musa

+0

之前,其實你的第一個例子工程和看跌期權'joe doe',但不等待超時... – Bergi

回答

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.somefunc()

但是當你做

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

爲您呼叫(不通過周圍)person.getName的getName的情況下被保留

+0

他有效地做的是'var somefunc = person.getName();',它將'somefunc()'設置爲'person.getName()'返回的任何內容。上下文不是問題,問題在於調用與引用。 – Barmar

+0

@Barmar我改變了代碼。看你假設你的意思:) – basarat

0
  1. 你說得太早。
  2. 當你保存一個沒有它所連接的對象的函數ref時,它會被破壞。

解決方案?

使用綁定和不早退叫它:

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

setTimeout(person.getName.bind(person), 2000); 
0

你的第一個功能對我來說工作正常(在Chrome測試):

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

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

setTimeout(person.getName(), 2000); 

也許還有另外一個問題別處?

+0

不起作用,它默默地失敗... – dandavis

+0

我更新了一個'alert'而不是console.log的代碼 - 對我來說似乎仍然工作正常兩種方式... – calipoop

+0

不,它立即啓動,沒有任何反應2秒呃... – dandavis

0

調用person.getName()執行函數並返回undefined(因爲在該函數中沒有聲明返回)。

你想要的是什麼:

setTimeout(person.getName, 2000); 

調用setTimeout(person.getName(), 2000);設置超時執行由person.getName()返回的結果是undefined而不是函數。

調用setTimeout(person.getName, 2000);設置超時以執行功能person.getName

用括號執行該函數。沒有括號傳遞變量(恰好被定義爲一個函數)。

編輯:作爲@Isaac指出,傳遞函數person.getName中也改變了this的行爲,這樣很可能你想要的不是兩種。

+0

'setTimeout(person.getName,2000)'是他實際上做的,否則他不會在控制檯上得到'undefined undefined'輸出... – Bergi

+0

@Bergi哦,對,我明白你的意思 –

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

+0

你是對的: http://javascriptweblog.wordpress.com/2010/08/30/understanding-javascripts-this/ –

+1

另外,請注意'setTimeout(person.getName,2000);'與'setTimeout(person.getName()不同, 2000);' – Isaac

+0

'人'不是範圍。這是調用'person.getName()'的上下文,並且該函數從來沒有「在」被「拉出」 – Bergi

1

我剛纔answerd類似的東西在這裏:

How can I pass a parameter to a setTimeout() callback?

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將執行在未來2s(2000ms)的第一個論點!

但你的第一個參數的價值是什麼? :你的函數的結果person.getName (), 所以它等價的:

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

這是非常不同的:

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

你傳遞一個函數的setTimeout的結果,第一種情況,其等待一個函數的引用。 在第二種情況下,你傳遞一個函數的引用(它是預期的),但不是在好的上下文中!

所以,現在你必須修復方面: 蒙山核心javascript函數:apply

現在試試這個:

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 ! 

希望這對你有所幫助!

編輯:

現代瀏覽器suporting綁定不採取有關護理做什麼說 here @dandavis