继承有几种方式,分别是什么,想要实现继承可以使用哪些方法
這里是修真院前端小課堂,每篇分享文從
【背景介紹】【知識剖析】【常見問題】【解決方案】【編碼實戰】【擴展思考】【更多討論】【參考文獻】
八個方面深度解析前端知識/技能,本篇分享的是:
【繼承有幾種方式,分別是什么,想要實現繼承可以使用哪些方法】
1.背景介紹
? ? ? 簡介
? ? ? ?在JS中繼承是一個非常復雜的話題,比其他任何面向對象語言中的繼承都復雜得多。在大多數其他面向對象語言中,繼承一個類只需使用一個關鍵字即可。在JS中想要達到繼承公用成員的目的,需要采取一系列措施。
?
2.知識剖析
? ??繼承有哪些方法可以實現?
? ? ?2.1.原型鏈
? ? ? ?原型鏈的基本思想是利用原型讓一個引用類型繼承另一個引用類型的屬性和方法。假如我們讓原型對象等于另一個類型的實例,結果會怎么樣呢?顯然,此時的原型對象將包含一個指向另一個原型的指針,相應地,另一個原型中也包含著一個指向另一個構造函數的指針。假如另一個原型又是另一個類型的實例,那么上述關系依然成立,如此層層遞進,就構成了實例與原型的鏈條。這就是所謂原型鏈的基本概念。
? ? ? ?實現原型鏈有一種基本模式,其代碼大致如下:
function Fn1() {this.property = true;//this綁定Fn1新對象 }//構造函數模式,函數名需大寫Fn1.prototype.getSuperValue = function () {return this.property;}; function Fn2() {this.subproperty = false; }//繼承了fn1 Fn2.prototype = new Fn1(); console.log(Fn2.prototype.property);//true Fn2.prototype.getSubValue = function () {return this.subproperty; };var instance = new Fn2(); console.log(instance.getSuperValue());//true? ??2.2.借用構造函數? ?? ? ??
? ? ? ?在解決原型中包含引用類型值所帶來問題的過程中,開發人員開始使用一種叫做借用構造函數的技術。這種技術的基本思想非常簡單,即在子類型構造函數的內部調用超類型構造函數。一般都是通過apply()和call()方法也可以在新創建的對象上執行構造函數。
?
function Fn1() {this.colors = ['red', 'blue', 'green']; } function ?Fn2() {Fn1.call(this);//繼承了Fn1對象 } var instance1 = new Fn2(); instance1.colors.push('black'); console.log(instance1.colors);//'red','blue','green','black'var instance2 = new Fn2(); console.log(instance2.colors);//'red','blue','green'*/? ? 2.3.組合繼承
? ? ? ? ??組合繼承,有時候也叫做偽經典繼承,指的是將原型鏈和借用構造函數的技術組合在一塊,從而發揮二者之長的一種繼承模式。其背后的思路是使用原型鏈實現對原型屬性和方法的繼承,而通過借用構造函數來實現對實例屬性的繼承。。這樣,既通過在原型上定義方法實現了函數復用,又能夠保證每個實例都有它自己的屬性。
?
function Fn1(name) {this.name = name;this.colors = ['red','blue','green']; } Fn1.prototype.sayName = function () {console.log(this.name); };function ?Fn2(name,age) {Fn1.call(this, name);//繼承Fn1屬性this.age = age; } //方法(函數)繼承 Fn2.prototype = new Fn1();//繼承Fn1的原型prototype Fn2.prototype.constructor = Fn2;//構造函數指向F2對象 Fn2.prototype.sayAge=function () {console.log(this.age); };var instance1 = new Fn2('Nicholas',29); instance1.colors.push('black'); console.log(instance1.colors);//'red','blue','green','black' instance1.sayName();//'Nicholas' instance1.sayAge();//29var instance2 = new Fn2('Freg',27); console.log(instance2.colors);//'red','blue','green' instance2.sayName();//'Greg' instance2.sayAge();//27? ? 2.4.原型式繼承
? ? ? ?道格拉斯·克羅克福德在一篇文章中介紹一種實現繼承的方法,這種方法并沒有實現嚴格意義上的構造函數。通過借助原型可以給予已有的對象創建新對象,同時還不必因此創建自定義類型。
?
function object(o) { function F() {} F.prototype = o; return new F(); }//借助原型可以基于已有的對象創建新對象 var person = {name:"Nicholas",friends:["Shelby","Court","Van"] };var anotherPerson = object(person);//相當于var anotherPerson = Object.create(person); anotherPerson.name = "Greg"; anotherPerson.friends.push("Rob");var yetAnotherPerson = object(person);//相當于var yetAnotherPerson = Object.create(person); yetAnotherPerson.name = "Linda"; yetAnotherPerson.friends.push("Barbie");console.log(person.friends);//"Shelby","Court","Van","Rob","Barbie"*/? ? 2.5.寄生式繼承? ? ?
? ???? ?寄生式繼承是與原型式繼承緊密關聯的一種思路,即創建一個僅用于封裝繼承過程的函數,該函數在內部以某種方式來增強對象,最后再想真地是它做了所有工作一樣返回對象
?
function object(o) {function F() {}F.prototype = o;return new F(); }//借助原型可以基于已有的對象創建新對象 function createAnother(original) {var clone = object(original);//通過調用函數創建一個新對象clone.sayHi = function () { //以某種方式來增強這個對象console.log("hi");};return clone;//返回這個對象 }var person = {name:"Nicholas",friends:["Shelby","Court","Van"] }; var anotherPerson = createAnother(person); anotherPerson.sayHi();? ?2.6.寄生組合式繼承? ??
? ? ? ?所謂寄生性繼承,即通過借用構造函數來繼承屬性,通過原型鏈的混成形式來繼承方法。
?
function object(o) {function F() {}F.prototype = o;return new F(); } function ?inheritPrototype(subType,superType) {var prototype = object(superType.prototype);//創建對象prototype.constructor=subType;//增強對象subType.prototype=prototype;//指定對象 } function Fn1(name) {this.name = name;this.colors=["red","blue","green"]; } Fn1.prototype.sayName=function () {console.log(this.name); }; function Fn2(name,age) {Fn1.call(this,name);//繼承Fn1的對象屬性this.age=age; } inheritPrototype(Fn1,Fn2); Fn2.prototype.sayAge = function () {console.log(this.age); }; var instance=new Fn2("Nicholas",29); instance.sayAge();//29 console.log(instance.colors);//["red","blue",""green] console.log(instance.name);//Nicholas3.常見問題
? ? ? 在以上的繼承方式中,哪些繼承方式比較好?
4.解決方案
? ? ? 現階段中運用比較廣泛的是組合式繼承,因為原型鏈和構造函數繼承方式都有相對應的缺點,比如說原型鏈最主要的問題來自包含引用類型值的原型。而構造函數的缺點是不能很好地封裝對象方法。一般情況下只有對象沒有方法的情況下才會使用構造函數。而組合式繼承繼承了原型鏈和構造函數的優點,并完善了二者的不足。
? ? ? `
?function Fn1(){
? ?this.colors=["red","blue","green"];
}
function Fn2(){
}
Fn2.prototype=new Fn1();//繼承了Fn1()對象
var instance1 = new Fn2();
instance1.colors.push("black");
console.log(instance1.colors);//"red","blue","green","black"
var instance2 = new Fn2();
console.log(instance2.colors);//"red","blue","green","black"
總結
以上是生活随笔為你收集整理的继承有几种方式,分别是什么,想要实现继承可以使用哪些方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Centos新建系统用户详解
- 下一篇: dubbo多网卡时,服务提供者的错误IP