2013-01-21 90 views
1

我在JS一個初學者,一直試圖讓下面的代碼工作,但它不給我預期的結果:JavaScript的原型繼承不工作

cat = function(name) { 
    this.name = name; 
    this.talk = function() { 
     alert("Cat "+name+" says meow."); 
    } 
} 
cat1 = new cat("George"); 
cat1.talk(); 

cat.prototype.changeName = function(name) { 
    this.name = name; 
} 
cat2 = new cat("Felix"); 
cat2.changeName("Bill"); 
cat2.talk(); 

從我瞭解JS,從第二次提醒我應該得到"Bill says meow"。不過貌似財產是沒有得到設置和我仍然得到"Felix says meow."

任何人可以指出錯誤了嗎?這將是非常有益的。提前致謝。

回答

2

這不是繼承的問題,它的訪問權變量的問題。看看你的構造函數:

cat = function(name) { 
    this.name = name; 
    this.talk = function() { 
     alert("Cat "+name+" says meow."); 
    } 
} 

具體alert("Cat "+name+" says meow.");name總是指的是你傳遞給構造函數的參數。你應該訪問this.name而是因爲你的changeName方法設置this.name到一個新的價值。

沒有理由雖然定義構造函數中的這種方法,將其添加到原型,以及:

var Cat = function(name) { 
    this.name = name; 
} 

Cat.prototype.talk = function() { 
    alert("Cat " + this.name + " says meow."); 
} 
+0

我明白了。你能否詳細解釋爲什麼名稱會引用傳遞給構造函數的參數而不是實際的字段?我來自Java背景,所以這有點奇怪。或者任何有用的URL也會有幫助。 – pflz

+0

這就是爲什麼我從不喜歡Java。它始終隱含地將未聲明的變量與實例屬性相關聯。在JavaScript中並非如此:構造函數中的參數稱爲'name',因此函數內的任何對'name'的引用(包括在其中定義的函數,即閉包)都引用該參數。 'this'是一個特殊的值,指的是函數被調用的上下文的對象。我建議閱讀https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/this。 –

+0

非常感謝您的幫助。 – pflz

1

您沒有使用繼承。我沒有看到你的代碼需要它在哪裏。

首先:你的「對話」功能需要訪問這個name屬性。不是。

Cat = function(name) { 
    this.name = name; 
    this.talk = function() { 
     alert("Cat "+this.name+" says meow."); //needs the to access this' name property 
    } 
} 

下一頁:你並不需要每一個實例被創建時重新聲明的通話方法:

Cat.prototype.talk = function(){ 
    ... 
} 

如果您確實需要繼承,你可以achive它:

var MainCoon = function(name){ 
    this.name = name; 
} 
MainCoon.prototype = new Cat(); 
MainCoon.prototype.be6ftTall = function(){ 

} 
+0

'MainCoon.prototype = new Cat();'是設置繼承的一種不好的方法。構造函數可能有副作用或接受參數等等。現在你想要做的就是將Cat的原型連接到原型鏈。你應該做'MainCoon.prototype = Object.create(Cat.prototype);'。 –

1

參照該指功能貓的實例,以便this.name是名稱的貓的實例的值。引用名字(沒有這個)是指構造函數之後的cat函數的名字。我想你可以也許看完這個獲得更深入的瞭解:

https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Inheritance_Revisited

沒有在頁面底部的下一個環節,當你到閉包的一部分,您能明白名字變量的作用域和this.name變量。

而且JavaScript是不是基於類的語言,但(一個根據一些執行不力)的原型語言:

http://www.lshift.net/blog/2006/07/24/subclassing-in-javascript-part-1

如果你的子類「子類」父母,或更好的說:如果你的childFunction使用parentFunction作爲他們的原型是知道,任何chidFunction「實例」,股吧慵懶副本的父如下例所示:

var parent,child,bill,suzan; 
parent=function(){ 
    this.name="parent"; 
    this.array=[]; 
} 
child=function(){ 
} 
child.prototype=new parent(); 
bill=new child(); 
bill.name="bill"; 
suzan=new child(); 
suzan.name="suzan"; 
suzan.array.push("done in suzan"); 
console.log(suzan.name);//correct is suzan 
console.log(bill.name);//correct is bill 
console.log(bill.array);//incorrect, shows ["done in suzan"] 

您可以通過更改「孩子」來解決這個問題:

child=function(){ 
    parent.call(this); 
} 

但是,只有在父函數體中使用this聲明對象屬性(不包括函數)時纔有效。語法而不是原型。