本文實例彙整了javascript關於繼承的用法。分享給大家供大家參考。具體如下:
範例:
/**
* 實作子類別繼承父類別,但不會產生多餘的屬性和方法
* @returns {Function}
*/
define(function(){
return function(subType, superType){
var proto = new Object(superType.prototype);
proto.constructor = subType;
subType.prototype = proto;
};
});
//——————————————————————————
define(function(){
function ostring(s)
{
this.str = s;
this.length = this.str.length;
}
ostring.prototype.show = function(){
alert(this.str);
};
return ostring;
});
//——————————————————————————
define(['inherit', 'ostring'], function(inherit, ostring){
function wstring(s){
//用call實作呼叫父類別建構子
ostring.call(this, s);
this.chlength = 2 * s.length;
}
//繼承其他的屬性
inherit(wstring, ostring);
wstring.prototype.add = function(w)
{
alert(this.str w);
};
return wstring;
});
再看範例
一、用function實作:
function Person(name) {
this.name = name;
}
Person.prototype.getName = function() {
return this.name;
}
function Author(name, books) {
this.inherit=person;
this.inherit(name);
this.books = books;
}
var au=new Author("dororo","Learn much");
au.name
或同等效力的:
function Person(name) {
this.name = name;
}
Person.prototype.getName = function() {
return this.name;
}
function Author(name, books) {
Person.call(this, name);
this.books = books;
}
var au=new Author("dororo","Learn much");
au.getName
由於這只是將this作為參數,呼叫父類Person的建構函數,把賦予父類別的所有域賦予Author子類,所以任何父類Person建構函數以外的定義的域(原型prototype),子類都不會繼承。所以上面範例中,au.getName將是沒有被定義的(undefined),因為getName是在Person的原型物件中定義的。
而且,子類別的建構子要在定義自己的域之前呼叫父類別建構函數,免得子類別的定義被父類別覆寫掉。也就是說,Author定義屬性book要在Person.call之後,否則會被Person中屬性覆寫。同時,在子類別中也最好不要用prototype來定義子類別的函數域,因為在一個子類別被new,實例化之後就要執行prototype,然後才是呼叫父類別的建構函數,這樣也容易被父類別的屬性覆蓋掉。
二、用prototype實作:
function Person(name) {
this.name = name;
}
Person.prototype.getName = function() {
return this.name;
}
function Author(name, books) {
this.books = books;
}
Author.prototype=new Person(name);
Author.prototype.constructor=Author;
Author.prototype.getBooks = function() {
return this.books;
}
var au1=new Author("dororo1","Learn much");
var au2=new Author("dororo2","Learn less");
alert(au1.getName());
alert(au2.getName());
這種方法避免了function實作中,無法繼承prototype的問題。因為 Author.prototype=new Person(name);new Person()實例會呼叫Person建構和原型的所有屬性。但是缺點是已經實例化了Author.prototype。所以當子類別實例化的時候,所有非基本資料型別都是reference copy。所以上面範例中,不論實例au1,或au2回傳的值都是dororo1.
三、用「混合」實現
function Person(name) {
this.name = name;
}
Person.prototype.getName = function() {
return this.name;
}
function Author(name, books) {
this.base = new Person(name);
for(var key in this.base){
if(!this[key]){
this[key]=this.base[key];
}
}
this.book=books;
}
var au1=new Author("dororo1","work");
var au2=new Author("dororo2","play");
alert(au1.getName());
alert(au2.getName());
au1.book;
au2.book;
屬於擴展,把父類別的所有域都拷貝到子類別。完全沒有上述兩方面的問題。
寄生組合模式)
JS的繼承包括屬性的繼承和方法的繼承,他們分別透過不同的方法來實現。
1.屬性的繼承
屬性的繼承是透過改變函數的執行環境來實現的。而改變函數的執行環境可以使用call()和apply()兩種方法來實作。
我們先建立一個Animal「類別」(因為JS中沒有類別的概念,這裡只是一個模擬,它其實只是一個Function函數物件)。
function Animal(typeName) {
//為目前方法的執行環境(this)新增一個屬性typeName
//但是執行環境(this)要執行這個函數的時候才能確定
this.typeName = typeName;
this.colors = ["red","while"];
}
//想函數的原型裡 新增 兩個(物件共享的)的方法
Animal.prototype.Shout = function () { alert("我是:--" this.typeName);};
Animal.prototype.Eat = function () { alert("我是:--" this.typeName) };
//--定義一個獅子--「類別」(其實就是一個函數)
function Lion(tn) {
//--執行Animal方法,並透過apply的第一個參數 修改了Animal的執行環境為Lion的this
//同樣的,Lion的this,也要在執行的時候才能確定是誰
Animal.apply(this,["獅子"]);//--繼承了父類別的變數屬性,this因為是new了Lion,this是Lion
}
Lion.prototype = Animal.prototype; //繼承父類別的方法,搞定--但是這寫不好,當子類別再添加方法時候,父類別同樣也有此方法,這是指標引用
Lion.prototype.Hunt = function () {
alert("我是:獅子,我要去捕獵~~·~");
}
var aminm = new Animal();
aminm.Hunt(); //---可以存取到子類別的方法,這樣就不好了
//----那麼如何解決這個問題呢》? ? ? ? ? ?
//---解:繼承方法時候可以這樣寫:
Lion.prototype = new Animal();//繼承父類別的方法,把Animal物件賦給了prototype原型,其實它裡面也有屬性
var lion = new Lion(); //new 關鍵字除了建立的,還會修改Lion物件的執行環境為Lion物件本身
// ---換句話說,就是new完了之後,Lion函數裡的this就是Lion函數本身了,然後呼叫Lion函數
分析一下new關鍵字:
而new關鍵字是十分偉大的,在上段程式碼中,new關鍵字完成了以下幾項工作:
1)開闢堆空間,以準備儲存Lion物件
2)修改Lion物件本身的執行環境,使得Lion函數的this指向了Lion函數物件本身。
3)呼叫Lion“類別”的“建構子”,建立Lion物件
4)將Lion函數物件的堆位址賦值給變數l,這個時候l指向了這個Lion函數物件
lion.Shout();
lion.Eat();
但是這種繼承有個缺點:就是父類別的建構子的被呼叫了兩次,call一次,然後new又一次。
希望本文所述對大家的javascript程式設計有所幫助。