實現繼承的幾種方式及工作原理
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,子類原型上有一份多餘的父類例項屬性,因為父類建構函式被呼叫了兩次,生成了兩份,而子類例項上的那一份遮蔽了子類原型上的。