2011-11-16 82 views
1

我掙扎着一個我以前認爲我理解的主題 - JavaScript中的原型繼承。JavaScript原型繼承混淆 - 我在這裏錯過了什麼?

我有我的概括問題here

我有一個基本對象和繼承實施的jsfiddle。我希望實現更改基本屬性,並讓基礎訪問這些更新的屬性。

任何人都可以請指出我要去哪裏錯了嗎?

+0

+1提供js小提琴。 –

回答

2

當你調用new cheeseBase()的的this值是您正在使用爲原型來自內部「切達()」的對象,而不是「切達」的實例。因此,「saySomething()」函數總是說「全部奶酪」,因爲它指的是構造函數調用中的「捕獲」this

如果您在「alert()」調用中更改「say​​Something()」以引用「this.favoriteCheese」,它會在彈出窗口中顯示「cheddar」。

如果你真的想子類進行修改的基本對象,或者,你可以重新排列:

function cheesebase() { 

    var that = this; 

    this.favouriteCheese = "all cheese"; 

    this.setBaseCheese = function(chz) { 
     that.favouriteCheese = chz; 
    }; 

    this.saySomething = function() { 
     alert("My favourite cheese is " + that.favouriteCheese); 
    }; 
} 

function cheddar() { 

    var returnObject = Object.create(new cheesebase()); 

    returnObject.setBaseCheese("cheddar"); 

    returnObject.saySomethingElse = function() { 
     alert("I like cheese"); 
    }; 

    return returnObject; 
} 
+0

我非常感謝您的意見。有沒有這種情況下,我會用'this'遇到麻煩?我知道它基於上下文而改變。如果我沒有使用任何關閉,我會好嗎? - 根據你原來的帖子,沒有'setCheeseBase'函數 – tomfumb

+0

2 tomfumb,你可能會遇到用戶界面回調的麻煩,通常是 $('#btn')。click(obj.saySomething);會將此綁定更改爲單擊元素的上下文。 –

+0

如果你接受我的第一個建議(在「saySomething()」中將「that」改爲「this」),那麼對該函數的調用將把this設置爲該類的* instance *。這意味着每個實例都將擁有自己的「favouriteCheese」屬性。這應該可以正常工作,但是您的問題指出,您希望**實例設置基類屬性。我不知道爲什麼,因爲它看起來像奶酪,因此會互相對抗,而奶酪的鬥爭是一個可怕的前景:-) – Pointy

1

也許你想達到什麼是這樣的:http://jsfiddle.net/yrU6y/1/

不管怎樣,在你原來的例子你沒有使用基礎對象的原型。這意味着,每次創建新的cheesebase時,都會重新定義其功能,即每個cheesebase對象都有自己的功能,而不是共享原型(並使用更少的內存)。

+0

謝謝,雖然jsfiddle是原來的一樣... – tomfumb

+0

對不起,它是http://jsfiddle.net/yrU6y/1/固定。 –

1

我最好猜測,下面的代碼會導致問題。

var that = this; 

我的原始直覺(不參考JS規範),重要的是原型基於繼承是基於原型對象的單個實例,如果沒有這種對象的複印。 那麼,this指針裏面cheeseBase指向原型對象,應該永遠不會改變。

後代方法和屬性綁定,在尋找方法或屬性時遍歷[this,this.prototype,this.prototype.prototype,...]序列,其中每個原型都意味着不可變的單例對象。

鑑於此,cheeseBase構造有this指向實際原型,將其存儲裏面的指針that和周圍that創建關閉,這是原型對象。

而且,在cheeseBase的綁定執行過程中this的綁定更改爲實際對象實例。

我想這樣的事情,可以在JS規範中的這個綁定下找到。