2013-03-07 67 views
3

要在Javascript中實現繼承,通常需要執行以下2個步驟;JavaScript繼承;調用和原型

說我有一個基類「動物」

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

我現在想從同一個派生一個子類「狗」。所以我會說

var Dog = function(name) { 
    Animal.call(this,name); 
} 

所以我從我的派生類構造函數調用我的父類構造函數。 第二步是設置原型如下;

Dog.prototype = new Animal(); 

現在我可以從我的派生類Dog中訪問任何基類「動物」類屬性。

所以我的問題是爲什麼這兩個步驟是必要的? 如果我們只需要調用使用

Animal.call(this,name); 

這還不夠實現繼承的基類的構造函數?

爲什麼我們需要使用Dog.prototype = new Animal();設置樣機屬性?

我想了解上述兩個步驟中的每一步是做什麼的?

+1

你沒有任何東西*繼承*在這裏。 – jAndy 2013-03-07 08:03:07

+1

因爲'動物'也可以使用原型鏈繼承。簡單地調用父構造函數將不會保留該繼承鏈。 – Sim 2013-03-07 08:03:22

+0

真的說call()只是從基類繼承屬性,而第二步(設置原型)從基類繼承方法? – testndtv 2013-03-07 08:41:16

回答

0

第一需要理解的是,在JavaScript中沒有經典繼承,我們從C語言(如Java,C#等)獲知的機制。在JavaScript中,代碼重用可以通過使用原型繼承來完成。我們唯一擁有的是對象,活着的代碼塊並且不需要實例化。例如:當一個函數在一個對象上被調用時 - 就像方法一樣,當前對象被檢查函數是否是已知的。如果找不到,引擎會調用它的原型(這是另一個對象),並檢查函數名是否已知並且可以調用。如果沒有找到,則會調用原型,依此類推。因此,設置對象的原型可以編排原型鏈。

要回答你的問題:沒有必要,它取決於你想要什麼。代碼重用是你想要的,繼承是你可以實現的方式(Stoyan Stefanov - JavaScript Patterns)。在JavaScript中,有更多的方法可用於重用代碼。

此外,這與當前上下文綁定,並不總是當前對象。

+0

所以當你說,當前對象被檢查是否該函數是已知的...如果沒有,它的原型被調用,等等...所以我們可以設置任何類型的對象的原型...就像我檢查方法myMethod1()在myObject1上,如果找不到,我可以在myObject2上進行下一次搜索...即我以某種方式將myObject1的原型(或父對象)設置爲myObject2 ... 我們可以用一個例子來展示... – testndtv 2013-03-07 08:35:00

+0

哈!你明白了!設置對象原型很簡單,如下所示:myobject.prototype = myobject2 – Andries 2013-03-07 09:01:06

+0

所以就像設置鏈接myobject的'_proto_'一樣。_proto = myobject2(但'_proto_'在除Firefox以外的所有瀏覽器中都不可訪問) – testndtv 2013-03-07 11:54:21

2
var Animal = function(name){ 
    this.name = name; 
} 
Animal.prototype.sleep = function() { 
    console.log("Sleeping") 
} 

... 
// Without this line: 
Dog.prototype = new Animal(); 

// the following code will fail, since `d` does not contain `sleep` 
d = new Dog(); 
d.sleep(); 

Animal.call(this,name);簡單地調用函數Animal,但使用相同this作爲調用函數。

Dog.prototype = new Animal();設置原型的原型。但是,Dog.prototype = Object.create(Animal.prototype)可能更正確。

+0

我對'Dog.prototype = Object.create()'不確定,因爲Object.create()'已經設置了新建對象的'.prototype'你通過。 – jAndy 2013-03-07 08:05:29

+0

@jAndy:那不是那種觀點?您希望'Dog.prototype .__ proto__'爲'Animal.prototype',以便成員繼承,但您不希望'Dog.prototype'成爲Animal的完整實例。 – Eric 2013-03-07 08:09:17

+0

在這種情況下,是的,沒錯。我錯了。 – jAndy 2013-03-07 08:11:11

0

第二步可以幫助您繼承原型方法。假設我們有更復雜的類:

function Animal(name) { 
    this.name = name; 
} 

// shared method 
Animal.prototype.say = function() { 
    alert(this.name); 
}; 

function Dog() { 
    Animal.apply(this, arguments); 
} 

Dog.prototype = new Animal(); 


var dog = new Dog('Cooper'); 
// method has been inherited 
dog.say(); // alerts 'Cooper' 

,您可以嘗試here

0

有沒有類,也沒有子類,在JavaScript。

調用並應用在不同的'this'上下文中執行一個函數。你的示例代碼中有什麼是不需要的。

//Create your constructor function: 
var Animal = function(){} 

Animal.prototype = { 
    sleep: function(){ 
     console.log('zzz'); 
    }, 
    bark: function(name){ 
     console.log(name +' barks!'); 
    } 
} 

var dog = new Animal(); 

dog.sleep(); 
dog.bark('asdasd'); 
+0

'var cat = new Animal();貓('貓');'。我認爲OP知道他們想在這裏繼承。 – Eric 2013-03-07 08:10:14

0

這裏我們定義構造函數的Animal

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

然後定義構造函數的Dog,並從裏面我們調用的Animal構造函數。就像我們在基於類的面向對象設計中做super()一樣。

var Dog = function(name) { 
    Animal.call(this,name); 
} 

然後我們通過消耗的 Animal原型定義的方法建立的Dog原型。這並不克隆方法Animal,但在鏈路建立DogAnimal使用它重新之間使用的方法Animal

Dog.prototype = new Animal(); 

並不斷擴展它增加更多的方法

Dog.prototype.showName = function(){ 
    // do something 
} 
1

一個代碼示例是勝過千言萬語:)

var Animal = function(name) { 
    this.name = name; 
} 
Animal.prototype.run = function() { 
    // do something 
}; 
var Dog = function(name) { 
    Animal.call(this, name); 
} 

var dog = new Dog('Puppy'); 
typeof dog.name; // "string" 
typeof dog.run; // "undefined" 
dog instanceof Animal; // false 
dog instanceof Dog; // true 

Dog.prototype = new Animal(); 

var dog = new Dog('Puppy'); 
typeof dog.name; // "string" 
typeof dog.run; // "function" 
dog instanceof Animal; // true 
dog instanceof Dog; // true 

正如你所看到的,如果你不使用Dog.prototype = new Animal();Animal.prototype成員不會被繼承。此外,Dog實例將不被視爲Animal的實例。