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