js基礎(chǔ)的面向?qū)ο蟮睦^承
構(gòu)造函數(shù)繼承
function Parent() {
this.name = 'parent'
}
function Child() {
Parent.call(this) //原理就是調(diào)用parent并且改變this的指向,指向當(dāng)前的this
this.type = 'child'
}
這種方法的缺陷是只會(huì)繼承構(gòu)造函數(shù)上的實(shí)例屬性,并不會(huì)繼承原型對(duì)象上的屬性,優(yōu)點(diǎn)就是如果parent上有引用類型的屬性,不會(huì)共用
借助原型鏈繼承
function Parent() {
this.name = 'parent'
}
Parent.prototype.say = function () {
console.log('say hello');
}
function Child() {
this.type = 'child'
}
Child.prototype = new Parent //通過原型鏈繼承把實(shí)例上的屬性和原型上的屬性都繼承了
缺點(diǎn)就是如果原型上的屬性有引用類型的,改變了其中一個(gè)實(shí)例上的引用屬性,另外一個(gè)也會(huì)改變,
構(gòu)造函數(shù)加原型鏈的繼承方式
function Parent() {
this.name = 'parent'
this.arr = [1,2,3]
}
Parent.prototype.say = function () {
console.log('say hello');
}
function Child() {
Parent.call(this) //繼承parent構(gòu)造函數(shù)里面的方法
this.type = 'child'
}
Child.prototype = new Parent //繼承構(gòu)造函數(shù)parent原型上的方法
這個(gè)綜合了兩種方法比較完美,但是parent構(gòu)造函數(shù)執(zhí)行了兩次,只是不必要的,也是對(duì)資源的一種浪費(fèi),稍微優(yōu)化下就好了
function Parent() {
this.name = 'parent'
this.arr = [1,2,3]
}
Parent.prototype.say = function () {
console.log('say hello');
}
function Child() {
Parent.call(this) //繼承parent構(gòu)造函數(shù)里面的方法
this.type = 'child'
}
Child.prototype = Parent.prototype//繼承構(gòu)造函數(shù)parent原型上的方法
這里還有個(gè)小缺陷,因?yàn)镃hild的原型和Parent的原型是同一個(gè)對(duì)象,所以constructor都會(huì)指向parent,所以就不能區(qū)分child構(gòu)造出來的實(shí)例到底是由Child構(gòu)造的還是Parent構(gòu)造的
于是還可以優(yōu)化一下
function Parent() {
this.name = 'parent'
this.arr = [1,2,3]
}
Parent.prototype.say = function () {
console.log('say hello');
}
function Child() {
Parent.call(this) //繼承parent構(gòu)造函數(shù)里面的方法
this.type = 'child'
}
Child.prototype = Object.create(Parent.prototype)//為什么要有這一步呢,如果直接執(zhí)行下面那一步,那么因?yàn)镃hild和Parent的原型是一樣的,所以如果直接改了Child原型上的prototype的構(gòu)造器屬性會(huì)導(dǎo)致Parent上的構(gòu)造器屬性也一樣指向了Child構(gòu)造函數(shù),這樣就失去意義了,所以要根據(jù)Object.create來當(dāng)一個(gè)中間對(duì)象,隔絕這層聯(lián)系
Child.prototype.constructor = Child;//修正一下構(gòu)造器屬性
ES6方式實(shí)現(xiàn)繼承
class Parent{
constructor(name){
this.name = name
}
getName(){
console.log(this.name);
}
}
class Child extends Parent{
//es6中主要通過extends去繼承原型鏈上面的,super去繼承實(shí)例上的
constructor(name,age){
super(name);
this.age = age
}
getAge(){
console.log(this.age);
}
}
const child = new Child('jj',18);
child.getName(); //jj
child.getAge(); //18
這里的constructor里面的super大概等于之前的 Parent.call(this)
這里就是面向?qū)ο罄^承的內(nèi)容了