第一種方式是藉助call實現繼承:面試
function Parent1(){
this.name = 'parent1';
}
function Child1(){
Parent1.call(this);
this.type = 'child1'
}
console.log(new Child1);
複製代碼
這樣寫的時候子類雖然可以拿到父類的屬性值,可是問題是父類原型對象中一旦存在方法那麼子類沒法繼承。那麼引出下面的方法。函數
第二種方式藉助原型鏈實現繼承:測試
function Parent2() {
this.name = 'parent2';
this.play = [1, 2, 3]
}
function Child2() {
this.type = 'child2';
}
Child2.prototype = new Parent2();
console.log(new Child2());
複製代碼
看似沒有問題,父類的方法和屬性都可以訪問,但實際上有一個潛在的不足。舉個例子:優化
var s1 = new Child2();
var s2 = new Child2();
s1.play.push(4);
console.log(s1.play, s2.play);
複製代碼
能夠看到控制檯:ui
明明我只改變了s1的play屬性,爲何s2也跟着變了呢?很簡單,由於兩個實例使用的是同一個原型對象。this
那麼還有更好的方式麼?spa
第三種方式:將前兩種組合:我,prototype
function Parent3 () {
this.name = 'parent3';
this.play = [1, 2, 3];
}
function Child3() {
Parent3.call(this);
this.type = 'child3';
}
Child3.prototype = new Parent3();
var s3 = new Child3();
var s4 = new Child3();
s3.play.push(4);
console.log(s3.play, s4.play);
複製代碼
能夠看到控制檯:3d
以前的問題都得以解決。可是這裏又徒增了一個新問題,那就是Parent3的構造函數會多執行了一次(Child3.prototype = new Parent3();)。這是咱們不肯看到的。那麼如何解決這個問題?code
第四種方式: 組合繼承的優化1
function Parent4 () {
this.name = 'parent4';
this.play = [1, 2, 3];
}
function Child4() {
Parent4.call(this);
this.type = 'child4';
}
Child4.prototype = Parent4.prototype;
複製代碼
這裏讓將父類原型對象直接給到子類,父類構造函數只執行一次,並且父類屬性和方法均能訪問,可是咱們來測試一下:
var s3 = new Child4();
var s4 = new Child4();
console.log(s3)
複製代碼
第五種方式(最推薦使用):優化2
function Parent5 () {
this.name = 'parent5';
this.play = [1, 2, 3];
}
function Child5() {
Parent5.call(this);
this.type = 'child5';
}
Child5.prototype = Object.create(Parent5.prototype);
Child5.prototype.constructor = Child5;
複製代碼
這是最推薦的一種方式,接近完美的繼承。
所以,小小的繼承雖然ES6當中簡化了不少,但毋庸置疑的是,js是一門基於原型的語言,因此,用ES5來完成繼承很是考驗面試者對JS語言自己的理解,尤爲是對於原型鏈是否理解清楚。
若是有更好的方式,歡迎在評論區交流。