前言
兩天沒寫了踩验,靠,怎么這么懶商玫,廢話不多說箕憾,來了來了。
繼承
子類能夠享有父類所擁有的屬性和方法拳昌,在創(chuàng)建類似實(shí)例的時候非常有用袭异。
原型鏈繼承
不知道大家有沒有搞清楚構(gòu)造函數(shù)、實(shí)例對象炬藤、原型對象之間的關(guān)系御铃,其實(shí)構(gòu)造函數(shù)也是一個對象,js一切皆對象嘛沈矿,function也是通過new Function()來創(chuàng)建的上真,而且
Function.prototype.__proto__ === Object.prototype
。
我想說的是:每個實(shí)例對象都是通過__proto__
指針來與其構(gòu)造函數(shù)的原型對象進(jìn)行關(guān)聯(lián)的羹膳,訪問屬性時就是按照這條原型鏈睡互。
第一種繼承:簡單的獲取到父類的屬性和方法
function Parent(name) {
this.name = name || 'parentName';
}
Parent.prototype.sayName = function () {
console.log(this.name);
}
function Son(age) {
this.age = age;
}
Son.prototype = new Parent();
const son1 = new Son(18);
- 原理:
instance.__proto__ == constructor.prototype;
上面說的關(guān)系鏈 - 缺點(diǎn):
- 所有實(shí)例共享父類的屬性和方法,一旦子類修改自身prototype的 屬性陵像,其他子類也會受到影響
- 只能繼承一個父類
- 子類在創(chuàng)建實(shí)例的時候無法向父類傳參
- 子類想要添加自己的原型方法和屬性必須在繼承之前操作
借用構(gòu)造函數(shù)繼承
子類在創(chuàng)建實(shí)例時可以傳遞參數(shù)給父類
function Parent(name) {
this.name = name || 'parentName';
}
Parent.prototype.sayName = function () {
console.log(this.name);
}
function Son(name, age) {
Parent.call(this, name);
this.age = age;
}
son1 = new Son("carter", 18);
- 原理:
call方法執(zhí)行父類的方法就珠,添加父類本身屬性給子類 - 缺點(diǎn):
- 每個子類實(shí)例都需要調(diào)用父類構(gòu)造函數(shù)
- 無法繼承父類的原型中的屬性和方法
- 并不屬于父類的實(shí)例,只屬于子類
原型加借用構(gòu)造函數(shù)繼承
前面兩種方法的綜合醒颖,借助原型鏈繼承父類的原型屬性和方法妻怎,借用構(gòu)造函數(shù)(可以傳參),繼承父類的屬性和方法图贸,不存在共享屬性的問題蹂季。
function Parent(name) {
this.name = name || 'parentName';
}
Parent.prototype.sayName = function () {
console.log(this.name);
}
function Son(name, age) {
Parent.call(this, name);
this.age = age;
}
Son.prototype = new Parent();
son1 = new Son("carter", 18);
缺點(diǎn):
- 需要調(diào)用兩次構(gòu)造函數(shù)
- 需要重寫子類原型的constructor屬性
組合式繼承
遇上述方法不同的是,在繼承原型屬性時疏日,直接將子類原型對象指向父類的原型對象偿洁,這樣就不需要調(diào)用兩次構(gòu)造函數(shù)了。
function Parent(name) {
this.name = name || 'parentName';
}
Parent.prototype.sayName = function () {
console.log(this.name);
}
function Son(name, age) {
Parent.call(this, name);
this.age = age;
}
Son.prototype = Parent.prototype;
son1 = new Son("carter", 18);
缺點(diǎn):
- 子類實(shí)例的constructor屬性指向不對
寄生式組合繼承
與組合式繼承不同的是沟优,在繼承原型屬性時涕滋,完全復(fù)制一個父類的原型對象指向子類原型。重寫constructor挠阁。
function Parent(name) {
this.name = name || 'parentName';
}
Parent.prototype.sayName = function () {
console.log(this.name);
}
function Son(name, age) {
Parent.call(this, name);
this.age = age;
}
Son.prototype = Object.create(Parent.prototype);
Son.prototype.constructor = Son;
// Object.create原理:
// Object.create = function (protoObj) {
// function F() {};
// F.prototype = protoObj;
// return new F();
// }
son1 = new Son("carter", 18);
ES6的class繼承
class Parent {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
}
class Son extends Parent {
constructor(name, age) {
super(name);
this.age = age;
}
}
son1 = new Son("carter", 18);
總結(jié)
ES5 的繼承宾肺,實(shí)質(zhì)是先創(chuàng)造子類的實(shí)例對象this溯饵,然后再將父類的方法添加到this上面(Parent.apply(this))。ES6 的繼承機(jī)制完全不同锨用,實(shí)質(zhì)是先將父類實(shí)例對象的屬性和方法丰刊,加到this上面(所以必須先調(diào)用super方法),然后再用子類的構(gòu)造函數(shù)修改this增拥。