-
原型鏈繼承
核心:子建構函式的原型指向父建構函式的例項
每個建構函式都有一個原型物件,原型物件中都包含一個指向建構函式的指標,而例項都包含一個指向原型物件的內部指標。當原型物件等於另外一個型別的例項即繼承。呼叫某個方法或者屬性的步驟
a.搜尋例項
b.搜尋原型
c.搜尋父類原型
function Animal() {
this.name = "animal";
this.arrt = [1, 2]
}
Animal.prototype = {
sayName: function () {
alert(this.name);
}
}
function Dog() {
this.color = "灰色"
}
Dog.prototype = new Animal();
Dog.prototype.sayColor = function () {
alert(this.color);
}
var dog = new Dog();
var dog1 = new Dog();
console.log(dog);
dog.arrt.push(5);
console.log(dog1);
dog.sayColor();
dog.sayName();
複製程式碼
可以自己列印一下,看一下結果
優點1.非常純粹的繼承關係,例項是子類的例項,也是父類的例項
2.父類新增原型方法/原型屬性,子類都能訪問到
3.簡單,易於實現
缺點
1.包含引用型別值的原型屬性會被所有例項共享,這會導致對一個例項的修改會影響另一個例項。
2.在建立子型別的例項時,不能向超型別的建構函式中傳遞引數。由於這兩個問題的存在,實踐中很少單獨使用原型鏈。
-
借用建構函式
也稱 "偽造物件" 或 "經典繼承",在子型別建構函式的內部呼叫超型別建構函式。函式不過是在特定環境中執行程式碼的物件,因此通過apply(),call()方法可以在(將來)新建物件上執行建構函式,即 在子型別物件上執行父型別函式中定義的所有物件初始化的程式碼。結果每個子類例項中都具有了父型別中的屬性以及方法
function Animal(name){
this.name = name;
this.colors = ["red","gray"];
}
function Dog(name){
//繼承了Animal
Animal.call(this,"mary");//在子型別建構函式的內部呼叫超型別建構函式
this.color = "gray";
}
Animal.prototype.sayName = function(){
alert(this.name);
}
var dog = new Dog();
var dog1=new Dog();
dog.colors.push("hhh");
console.log(dog.colors);//red gray hhh
console.log(dog1.colors);//red gray
Animal.prototype.swif="hua";
console.log(dog.swif);//undefined
var animal = new Animal();
console.log(animal); //如果將函式定義在建構函式中,函式複用無從談起
dog.sayName(); //在超型別的原型中定義的方法,對於子型別而言是無法看到的
複製程式碼
優點
1.解決了1中,子類例項共享父類引用屬性的問題
2.建立子類例項時,可以向父類傳遞引數
3.可以實現多繼承(call多個父類物件)
缺點
1.例項並不是父類的例項,只是子類的例項
2.只能繼承父類的例項屬性和方法,不能繼承父類原型屬性/方法
3.無法實現函式複用,每個子類都有父類例項函式的副本,影響效能
-
組合函式
組合繼承(combination inheritance),有時候也叫做偽經典繼承,指的是將原型鏈和借用建構函式的 技術組合到一塊,從而發揮二者之長的一種繼承模式。其背後的思路是使用原型鏈實現對原型屬性和方 法的繼承,而通過借用建構函式來實現對例項屬性的繼承。這樣,既通過在原型上定義方法實現了函式 複用,又能夠保證每個例項都有它自己的屬性
function Animal(name){
this.name = name;
this.colors = ["red","gray"];
}
function Dog(name){
//繼承了Animal(屬性)
Animal.call(this,name);
this.color = "gray";
}
Animal.prototype.sayName = function(){
alert(this.name);
}
//繼承方法
Dog.prototype = new Animal();
Dog.prototype.constructor = Animal;
var dog = new Dog("2");
dog.colors.push("hhh");
console.log(dog);
var animal = new Animal();
console.log(animal);
dog.sayName(); //可以呼叫
複製程式碼
優點
1.可以繼承例項屬性/方法,也可以繼承原型屬性/方法
2.既是子類的例項,也是父類的例項
3.不存在引用屬性共享問題
4.通過call繼承父類的基本屬性和引用屬性並保留能傳參的優點
5.函式可複用
缺點
1,子類原型上有一份多餘的父類例項屬性,因為父類建構函式被呼叫了兩次,生成了兩份,而子類例項上的那一份遮蔽了子類原型上的。
-
原型式繼承
-
寄生式繼承
-
寄生組合式繼承