js創(chuàng)建之初,正值java大行其道,面向?qū)ο缶幊檀猴L正盛,js借鑒了java的對象機制,但僅是看起來像,也就是js的構(gòu)造函數(shù),如下:
function People(age) {
this.age = age;
this.getAge = function (){return this.age};
}
var p1 = new People(20);//People的實例1
var p2 = new People(40);//People的實例2
上面的代碼很像java了,通過new constructor()的方式,可以創(chuàng)建多個實例。
但上面代碼問題是getAge方法會在每個People的實例中存在,如果實例多的話,會浪費很多空間,js采用了犧牲時間,獲取空間的方法,js引入了原型理念,將方法放入原型中:
function People(age) {
this.age = age
}
People.prototype.getAge = function () {return this.age};
本文就來總結(jié)下,如何使用構(gòu)造函數(shù)來實現(xiàn)繼承。
我們假設(shè)我們有一個父構(gòu)造函數(shù)People和子構(gòu)造函數(shù)Student,People有一個屬性age和一個方法getAge,Student有一個屬性num和getNum。
function People(age) {
this.age = age;
}
People.prototype.getAge = function (){return this.age;};
function Student(num) {
this.num = num;
}
Student.prototype.getNum = function () {return this.num;};
我們要實現(xiàn)是Student繼承People,這在js里可要費一番力氣了。
我們可以利用js的原型機制,將子構(gòu)造函數(shù)的原型屬性設(shè)置為父構(gòu)造函數(shù)的實例,這是js中比較常用的方式:
function Student(num) {
this.num = num;
}
Student.prototype = new People();
Student.prototype.getNum = function () {return this.num;};
var stu1 = new Student('123');
這樣做其實基本實現(xiàn)了我們的需求,但如果深入思考上面的方式,其實有幾個缺點:
哦?。?!
先來看看如何解決第一個問題,我們可以巧用js的call方法,如果你還不知道這個方法,請移步這里。
function Student(age, num) {
People.call(this, age);
this.num = num;
}
我們在子構(gòu)造函數(shù)內(nèi)部,借用父構(gòu)造函數(shù),這樣就巧妙地在子類中繼承了父類的實例化屬性。這其實類似java的super關(guān)鍵字。
再來看看如何解決第二個問題,解決這個問題,其實我們可以將子構(gòu)造函數(shù)的原型更改為父構(gòu)造函數(shù)的原型,而不是父構(gòu)造函數(shù)的實例。
Student.prototype = People.prototype;
這樣就不會將父構(gòu)造函數(shù)的實例屬性擴展到子構(gòu)造函數(shù)的原型上了。
但這樣做會導(dǎo)致另一個問題,就是無法再在Student的原型上擴展方法了,因為會擴展同時會擴展到People的原型上。
為了解決上面引發(fā)的問題,和第三個問題。我們可以在子構(gòu)造函數(shù)和父構(gòu)造函數(shù)之間,加一層臨時構(gòu)造函數(shù)。
function F() {
}
F.prototype = People.prototype;
Student.prototype = new F();
這樣就可以Student的原型上擴展子構(gòu)造函數(shù)的方法,同時不影響父構(gòu)造函數(shù)的原形了。
在修復(fù)一下constructor屬性就ok啦
Student.prorotype.constructor = Student;
我們將上面的幾種方法綜合起來,代碼看起來就像下面這樣子:
//繼承函數(shù)
function inherit(C, P) {
var F = function (){};
F.prototype = P.prototype;
C.prototype = new F();//臨時構(gòu)造函數(shù)
C.prototype.constructor = C;//修復(fù)constructor
C.uper = P;//存儲超類
}
function People(age) {
this.age = age;
}
People.prototype.getAge = function (){return this.age;};
function Student(age, num) {
Student.uber.call(this, age);
this.num = num;
}
inherit(Student, People);//繼承父構(gòu)造函數(shù)
Student.prototype.getNum = function () {return this.num;};
本文大部分內(nèi)容其實出自,《javascript模式》第五章 代碼的復(fù)用模式。記錄下來省的自己每次都要去翻書了,當然主要還是寫給MM看的。
更多建議: