2011-11-03 205 views
2

任何人都可以告訴我爲什麼我的'showDiv_boo'在類的方法內未定義嗎? 我也無法訪問我的班級的方法。Javascript類繼承

Here's我的班 '眨眼',其屬性和方法的類:

function Blink(div) { 
    this.div = div 
} 
Blink.prototype.counter = 0 
Blink.prototype.showDiv_boo = true 
Blink.prototype.showDiv = function() { 
    this.div.style.visibility = 'visible' 
} 
Blink.prototype.hideDiv = function() { 
    this.div.style.visibility = 'hidden' 
} 
Blink.prototype.startEngine = function() { 
    if (this.showDiv_boo) { 
     this.showDiv() 
    } else if (!this.showDiv_boo) { 
     this.hideDiv() 
    } 
    this.showDiv_boo = !this.showDiv_boo 
    this.counter++ 
} 
Blink.prototype.startEffect = function() { 
    this.idEffect = setInterval(this.startEngine, 1000/45) 
} 

所以,如果我創建:

_blink = new Blink(myDiv); 
_blink.startEffect(); 

您可以測試...變量 'showDiv_boo' ,在方法內部是未定義的。

即使我將showDiv_boo設置爲true,它也不會調用我的類的方法showDiv或hideDiv。

有人嗎?

謝謝:)

回答

3

您需要:

  1. 使用var self並通過self.startEngine()
  2. 調用該方法可以使用匿名函數來包裝通話[1]即function(){ self.startEngine(); }

這是因爲當你只是通過this.startEngineself.startEngine你只是傳遞函數startEngine而不指定什麼this是,在兩種情況下都是由gl提供的DOMWindow的實際圓錐體文字。

舉個例子...

function startEngine() { 
    ...code omitted... 
}; 

Blink.prototype.startEngine = startEngine; 

Blink.prototype.start = function() { 
    setTimeout(startEngine, 0);  // obviously wrong, what is this? 
    setTimeout(Blink.startEngine, 0); // actually the same as line above, although not as obvious 
    setTimeout(startEngine.bind(this), 0); // works correctly 
} 

工程代碼添加到原型,如果在匿名函數中使用可以發揮預期的,但如果你只是用Blink.startEngine作爲回調是完全與使用startEngine相同,只有第二個更明顯錯誤,因爲沒有任何對象被調用,因此您期望this是由上下文提供的任何對象。

你能做到這一點不使用匿名函數的另一種方法是

Blink.startEngine.bind(self) 

它返回將調用startEngine用正確的this一樣明確創建匿名函數和包裝調用self.startEngine()功能

繼承人到小提琴的鏈接玩的差異:http://jsfiddle.net/bonza_labs/MdeTF/

+0

它工作正常,謝謝:) –

5

之所以是,startEnginesetInterval調用。調用回調的方式會導致startEngine對於this具有與startEffect不同的值。您需要保存this以便將其保留在回調中。例如。

Blink.prototype.startEffect = function() { 
    var self = this; 
    self.idEffect = setInterval(function() { self.startEngine(); }, 1000/45); 
}; 
+0

嗨。 我試過使用'var self'和相同的東西。 showDiv_boo在startEngine方法內部是未定義的。 –

+0

想想你可能不會把它包裝在匿名函數中 - 兩者都是關鍵。如果你不使用匿名函數'self.startEngine'和'this.startEngine'完全一樣。請參閱我的答案進一步解釋。 – craigb

0

如果你做到以下幾點,你會發現它被定義

var x = new Blink('hello'); 
x.showDiv_boo 

JavaScript使用原型繼承。雖然showDiv_boo可能沒有在Blink實例中明確定義,但它確實存在於Blink從中繼承的原型中。當您嘗試從對象內引用showDiv_boo時,JavaScript引擎會實現該對象不具有該名稱的成員,然後將檢查其原型。

+0

如何在'startEngine'方法內訪問'showDiv_boo'? 謝謝:) –

0

隨着設置時間變量來存儲this,你必須調用startEngine()函數變量:

Blink.prototype.startEffect = function(){ 
    var self = this; 
    self.idEffect = setInterval(function(){ self.startEngine.call(self); }, 1000/45); 
} 

注意在startEngine.call(self),基本要求與變量self的功能,所以變量this將是正確的。

+0

只需調用'self.startEngine()'就足夠你不需要也顯式綁定調用自我再次。 – craigb