js面試題繼承的方法及優(yōu)缺點(diǎn)解答
說(shuō)一說(shuō)js繼承的方法和優(yōu)缺點(diǎn)?
要點(diǎn): 原型鏈繼承、借用構(gòu)造函數(shù)繼承、組合繼承、原型式繼承、寄生式繼承、寄生組合式繼承、ES6 Class
答:
一、原型鏈繼承
缺點(diǎn):
- 1.引用類(lèi)型的屬性被所有實(shí)例共享
- 2.在創(chuàng)建 Child 的實(shí)例時(shí),不能向 Parent 傳參
//原型鏈繼承 function Parent() { this.parentPrototype = "parent prototype" //驗(yàn)證這種繼承方法的確定,如果父類(lèi)示例中存在一個(gè)引用類(lèi)型的屬性,將會(huì)被所有子類(lèi)共享 this.parentObj = { info: "我是 parent 引用屬性parentObj中的 info" } } function Children() { } //將Children的原型對(duì)象指定為Parent的示例,通過(guò)原型鏈,將Parent中的屬性賦值給Children示例 Children.prototype = new Parent(); const a = new Children(); console.log(a.parentPrototype); // parent prototype //缺點(diǎn) const b = new Children(); //在a示例中改動(dòng)繼承的引用屬性 a.parentObj.info = "我是a示例中 引用屬性parentObj中的 info" //b與a示例共享引用屬性 console.log(b.parentObj.info); // 我是a示例中 引用屬性parentObj中的 info
二、借用構(gòu)造函數(shù)(經(jīng)典繼承)
優(yōu)點(diǎn):
- 1.避免了引用類(lèi)型的屬性被所有實(shí)例共享
- 2.可以在 Child 中向 Parent 傳參
缺點(diǎn):
- 1.方法都在構(gòu)造函數(shù)中定義,每次創(chuàng)建實(shí)例都會(huì)創(chuàng)建一遍方法。
function Parent() { this.parentPrototype = "parent prototype" this.obj = { info: "parent obj info" } this.fn = function () { console.log("打印功能") } } function Children() { Parent.call(this); } const a = new Children(); console.log(a.parentPrototype); // parent ptototype //缺點(diǎn) 此時(shí)Parent()會(huì)再次創(chuàng)建一個(gè)fn函數(shù),這個(gè)是沒(méi)有必要的 const b = new Children(); a.obj.info = "a obj info"; //優(yōu)點(diǎn) 避免了子類(lèi)實(shí)例共享引用屬性 console.log(b.obj.info) // parent obj info;
三、組合繼承
優(yōu)點(diǎn):
- 1.融合原型鏈繼承和構(gòu)造函數(shù)的優(yōu)點(diǎn),是 JavaScript 中最常用的繼承模式。
function Parent() { this.parentPrototype = "我是Parent 中的屬性" } //Parent中的方法,在原型上定義 Parent.prototype.pFn = function () { console.log('我是Parent中的方法'); } function Children() { //Parent中的屬性仍然在構(gòu)造函數(shù)中繼承 Parent.call(this); } //將Children的原型對(duì)象賦值為 Parent實(shí)例,這樣Parent中的方法也能夠被Children繼承 Children.prototype = new Parent(); const c = new Children(); console.log(c.parentPrototype); //我是Parent 中的屬性 c.pFn(); //我是Parent中的方法
四、原型式繼承
缺點(diǎn): - 1.包含引用類(lèi)型的屬性值始終都會(huì)共享相應(yīng)的值,這點(diǎn)跟原型鏈繼承一樣。
function objFn(o) { o.objFnPrototype = "我是 objFnPrototype" function F() {} F.prototype = o; return new F(); } let a = objFn({ name: "name1" }); console.log(a.name); //name1 console.log(a.objFnPrototype); //我是 objFnPrototype
五、寄生式繼承
缺點(diǎn):
- 1.跟借用構(gòu)造函數(shù)模式一樣,每次創(chuàng)建對(duì)象都會(huì)創(chuàng)建一遍方法。
function createObje(obj) { let clone = Object.assign(obj); //接受到對(duì)象后,原封不動(dòng)的創(chuàng)建一個(gè)新對(duì)象 clone.prototype1 = "我是新增的prototype1"; //在新對(duì)象上新增屬性,這就是所謂的寄生 return clone; //返回新對(duì)象 } const parent = { parentPrototype: "parentPrototype" } //c實(shí)例,就繼承了parent的所有屬性 let c = createObje(parent); console.log(c.parentPrototype); //parentPrototype
六、寄生組合式繼承
優(yōu)點(diǎn):
- 1.這種方式的高效率體現(xiàn)它只調(diào)用了一次 Parent 構(gòu)造函數(shù),并且因此避免了在 Parent.prototype 上面創(chuàng)建不必要的、多余的屬性。
- 2.與此同時(shí),原型鏈還能保持不變;
- 3.因此,還能夠正常使用 instanceof 和 isPrototypeOf。
function inherProto(superType, subType) { //拷貝一個(gè)超類(lèi)的原型副本 let proto = { ...superType.prototype }; //將原型的超類(lèi)副本作為子類(lèi)的原型對(duì)象,也就是第一種中的原型鏈繼承方式,只不過(guò)繼承的是超類(lèi)原型的副本 subType.prototype = proto; //這一步比較迷,官方的說(shuō)法是,我們?cè)诳截惓?lèi)的原型的時(shí)候,拷貝的proto對(duì)象,將會(huì)丟失默認(rèn)自己的構(gòu)造函數(shù),也就是superType, //所以我們這里將它的構(gòu)造函數(shù)補(bǔ)全為subType。貌似不做這一步也沒(méi)啥問(wèn)題,但是缺了點(diǎn)東西可能會(huì)有其他的副作用,所以還是補(bǔ)上 proto.constructor = subType; } function Super() { this.superProto = "super proto"; this.colors = ["red", "yelloy"]; } function Sub() { this.subProto = "sub proto"; this.name = "sub name"; //這里還是借用構(gòu)造函數(shù)的套路 Super.call(this); } Super.prototype.getName = function () { console.log(this.name); } //這里要在定義完Super的屬性后執(zhí)行,因?yàn)槔^承的是超類(lèi)原型的副本,與Super.prototype是兩個(gè)對(duì)象,在這之后再改變Super.prototype,就已經(jīng)不會(huì)在影響到Sub所繼承的副本超類(lèi)原型對(duì)象了 inherProto(Super, Sub); let a = new Sub(); console.log(a.getName);
以上就是js面試題繼承的方法及優(yōu)缺點(diǎn)解答的詳細(xì)內(nèi)容,更多關(guān)于js面試題繼承方法優(yōu)缺點(diǎn)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
js基于div絲滑實(shí)現(xiàn)貝塞爾曲線(xiàn)
這篇文章主要為大家介紹了js基于div絲滑實(shí)現(xiàn)貝塞爾曲線(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09Javascript中bind()方法綁定函數(shù)的使用與實(shí)現(xiàn)
這篇文章主要為大家介紹了Javascript中bind()方法綁定函數(shù)的使用與實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06js c++ vue方法與數(shù)據(jù)交互通信示例
這篇文章主要為大家介紹了js c++ vue方法與數(shù)據(jù)交互通信示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08lodash內(nèi)部方法getFuncName及setToString剖析詳解
本篇章我們主要是通過(guò)了解lodash里的兩個(gè)內(nèi)部方法getFuncName方法和setToString方法,在實(shí)際開(kāi)發(fā)中我們也可以借鑒方法的實(shí)現(xiàn)思路,在需要的時(shí)候簡(jiǎn)單封裝一下,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09