一 原型鏈繼承
原型鏈繼承的原理:直接讓子類的原型物件指向父類例項,當子類例項找不到對應的屬性和方法時,就會往它的原型物件,也就是父類例項上找,從而實現對父類的屬性和方法的繼承。
// 父類
function
fat(
)// 父類上的原型方法
fat.prototype.
getname
=function()
// 子類
function
child()
// 子類的原型物件方法指向父類 子類中找不到的屬性方法就會向父類找
child.prototype =
newfat()
// 不影響繼承 順便綁一下constructor
child.prototype.constructor = child
// child例項就可以訪問父類及其原型上的屬性和方法了
const child =
newchild()
child.name // 'zaq'
child.
getname()
// 'zaq'
原型鏈繼承的缺點1、所有的child例項原型都指向同乙個fat例項,因此對child例項修改某個父類引用型別會影響所有的child例項;
2、建立子類時無法向父類傳參,沒有實現super()的功能
function
fat(
)fat.prototype.
getname
=function()
function
child()
child.prototype =
newfat()
child.prototype.constructor = child
//const child1 =
newchild()
;const child2 =
newchild()
;child1.name =
'lsq'
console.
log(child1.name)
// lsq
// 本來父類name屬性是zaq 然後現在==
console.
log(child2.name)
// lsq
二 建構函式繼承
建構函式繼承:在子類的建構函式中執行父類的建構函式,並為其繫結子類的this。讓父類的建構函式把成員的屬性和方法都掛在子類的this上,這樣既避免了共用乙個原型例項,又能像父類建構函式傳參。
function
fat(name)
fat.prototype.
getname
=function()
function
child()
const child1 =
newchild()
const child2 =
newchild()
child1.name =
'xyc'
console.
log(child1.name)
// xyc
console.
log(child2.name)
// zaq
建構函式繼承的缺點繼承不到父類上的屬性和方法
child1.
getname()
// uncaught typeerror: child1.getname is not a function
三 組合式繼承
既然原型鏈繼承和建構函式繼承都有各自的缺點但是又能互補,那何不將兩者結合起來使用;
function
fat(name)
fat.prototype.
getname
=function()
// 建構函式繼承
function
child()
// 原型鏈繼承
child.prototype =
newfat()
child.prototype.constructor = child
const child1 =
newchild()
const child2 =
newchild()
child1.name =
'lsq'
console.
log(child1.name)
// lsq
console.
log(child2.name)
// zaq
child1.
getname()
// lsq
組合式繼承的缺點每次建立子類例項都執行了兩次建構函式(fat.call()和new fat()),雖然不影響繼承,但是在子類建立時 原型中會存在兩份相同的屬性和方法。
四 寄生式組合繼承
為了解決建構函式被執行兩次的問題,我們將指向父類例項變成轉向父類原型,減少一次建構函式的執行
function
fat(name)
fat.prototype.
getname
=function()
// 建構函式繼承
function
child()
// 原型鏈繼承
child.prototype = fat.prototype // 將指向父類例項轉成轉向父類原型
child.prototype.constructor = child
const child1 =
newchild()
const child2 =
newchild()
child1.name =
'lsq'
console.
log(child1.name)
// lsq
console.
log(child2.name)
// zaq
child1.
getname()
// lsq
但是這種方法也存在乙個問題,就是子類和父類的原型都指向同乙個物件,如果我們對子類原型操作就會對父類原型產生影響。比如給子類child.prototype新增乙個getname方法,那麼父類fat.prototype也增加或是被覆蓋乙個getname方法。為了解決這個問題 我們給fat.prototype做乙個淺拷貝;
function
fat(name)
fat.prototype.
getname
=function()
// 建構函式繼承
function
child()
// 原型鏈繼承
child.prototype = object.
create
(fat.prototype)
// 將指向父類例項轉成轉向父類原型
child.prototype.constructor = child
const child1 =
newchild()
;const child2 =
newfat()
;child1.
getname()
// zaq
child2.
getname()
// undefined
到這裡我們就完成了es5裡的繼承,有空更新es6的繼承方法
class介紹 來自阮一峰
es6中的繼承:
1、class可以理解為functon,由於class本質還是乙個function,因此它也有乙個prototype屬性。當new乙個class時,會把class的protortype屬性賦值給這個新物件的_proto_屬性上;
2、constructor是預設新增的方法,在new乙個物件的時候,會自動呼叫該方法, constructor裡定義自己的屬性;
3、繼承extends和super, class子類名 extends父類名 實現繼承。當然,還得在constructor裡寫上super (父類的引數),意思就是在子類中獲取父類的this指標,相當於fat.call(this),參考
// 父類
class
fatgetname()
}// 繼承
class
child
extends
fat// 子類自己的方法
getfatname()
getattrs()
}// 通過new例項化乙個建構函式
const child1 =
newchild(,
'mine attrs'
)child1.
getname()
// zaq
child1.
getrename()
// zwj
child1.
getattrs()
// mine attrs
end… 散會 ES5 ES6 實現繼承
function parent value parent.prototype.getvalue function function child value child.prototype new parent const child new child 1 child.getvalue 1我們來研究...
ES5,ES6中的繼承
es5中的繼承 1,借助建構函式實現繼承 只能實現部分繼承 原理 通過call 函式改變this指向,將父類屬性掛載到子類例項中 function parent function child console.log new child 總結 優點 只呼叫一次父類的建構函式,避免了在子類原型中建立不必...
ES5,ES6中的繼承
es5中的繼承 1,借助建構函式實現繼承 只能實現部分繼承 原理 通過call 函式改變this指向,將父類屬性掛載到子類例項中 function parent function child console.log new child 總結 優點 只呼叫一次父類的建構函式,避免了在子類原型中建立不必...