2013-08-17 62 views
2

獲得更多的Javascript和OO編程,但我不理解這種行爲在這裏爲什麼我的ojbect(myUser不能訪問屬性this.first_name'jon',而是未定義(加亮後在底部時的屏幕截圖紅)這裏是有問題的代碼片斷:關閉此JavaScript行爲在關閉

function User(first_name, last_name){ 
    this.first_name=first_name; 
    this.last_name=last_name; 
} 

// left in for completeness 
User.prototype = { 
    constructor: User, 
    sayName: function(){ 
     console.log("My Name: " + this.first_name + " and " + this.last_name); 
    } 

} 

User.prototype.whoWhat = function(){ 
    console.log(this.first_name + " I want to tell you now " + Math.random()); 
} 

var myUser=new User('jon', 'johnson'); 
myUser.sayName(); 
myUser.whoWhat(); 
setInterval(myUser.whoWhat, 3000); 

,這裏是控制檯輸出:

enter image description here

回答

6

的問題是,你的setInterval()回調會失去與您構建的對象的關聯。函數與對象的關聯作爲屬性值只有影響this當屬性值用於進行函數調用時。在這裏,你只是引用這個值(也就是說,獲取對該函數的引用)。當系統調用該函數時,this將爲undefined(或window對象,具體取決於「嚴格」模式)。

可以確保this是使用包裝函數正確的價值:

setInterval(function() { myUser.whoWhat(); }, 3000); 

在新的瀏覽器,你可以使用從函數原型的方法稱爲bind()

setInterval(myUser.whoWhat.bind(myUser), 3000); 

那(爲了您的目的)具有相同的效果,但bind()也可以做其他事情。

要記住的關鍵是在JavaScript中,函數和對象之間沒有長期的關係。對函數的引用只是簡單的值,沒有什麼特別的事情發生,因爲函數恰好被定義爲原型對象或對象文本的屬性。唯一重要的是如何調用一個函數。

+0

THX的答案尖!你的代碼絕對有效,但我沒有完全明白。我可能會重讀10次。 thx再次。 – timpone

3

此行爲被稱爲MDN文檔中的「本」的問題:通過的setInterval()執行

代碼是在單獨的執行上下文 到從它被調用的函數運行。因此,被調用函數的這個關鍵字 將被設置爲窗口(或全局) 對象,它將不會與調用setTimeout的函數 的此值相同。

https://developer.mozilla.org/en-US/docs/Web/API/window.setInterval

2

當你訪問一個屬性,它是一個功能,還有就是如果你直接調用它,或者如果你保持基準,後來稱之爲差異。

當您直接調用它時,該對象將用作上下文,但如果您稍後保留該引用,則它不再與該對象相關聯,並且當您調用它時,將使用全局對象調用它(窗口)作爲上下文。

的解決方案是使該方法調用的函數setTimeout調用使用方法:

setInterval(function(){ myUser.whoWhat(); }, 3000); 
+0

thx回答,這部分總是讓我感到困惑。 – timpone