衆所周知,在ES6
以前,前端是不存在類的語法糖,因此不能像其餘語言同樣用extends
關鍵字就搞定繼承關係,須要一些額外的方法來實現繼承。下面就介紹一些經常使用的方法,紅寶書已經歸納的十分全面了,因此本文基本就是對紅寶書繼承篇章的筆記和梳理。前端
function Parent() {
this.name = 'arzh'
}
Parent.prototype.getName = function () {
console.log(this.name)
}
function Child() {
}
//主要精髓所在
Child.prototype = new Parent()
Child.prototype.constructor = Child
var arzhChild = new Child()
arzhChild.getName() // 'arzh'
複製代碼
原型鏈繼承缺點:bash
function Parent() {
this.names = ['arzh','arzh1'];
}
function Child() {
}
//主要精髓所在
Child.prototype = new Parent()
Child.prototype.constructor = Child
var arzhChild2 = new Child()
arzhChild2.names.push('arzh2')
console.log(arzhChild2.names) //[ 'arzh', 'arzh1', 'arzh2' ]
var arzhChild3 = new Child()
arzhChild3.names.push('arzh3')
console.log(arzhChild3.names) //[ 'arzh', 'arzh1', 'arzh2', 'arzh3' ]
複製代碼
Child
實例的時候,沒法向Parent
傳參。這樣就會使Child
實例無法自定義本身的屬性(名字)function Parent() {
this.names = ['arzh','arzh1']
}
function Child() {
Parent.call(this)
}
var arzhChild2 = new Child()
arzhChild2.names.push('arzh2')
console.log(arzhChild2.names) //[ 'arzh', 'arzh1', 'arzh2' ]
var arzhChild3 = new Child()
arzhChild3.names.push('arzh3')
console.log(arzhChild3.names) //[ 'arzh', 'arzh1', 'arzh3' ]
複製代碼
優勢:函數
function Parent(name) {
this.name = name
}
function Child(name) {
Parent.call(this, name)
}
var arzhChild = new Child('arzh');
console.log(arzhChild.name); // arzh
var arzhChild1 = new Child('arzh1');
console.log(arzhChild1.name); // arzh1
複製代碼
缺點:優化
function Parent(name) {
this.name = name
this.body = ['foot','hand']
}
function Child(name, age) {
Parent.call(this, name)
this.age = age
}
Child.prototype = new Parent()
Child.prototype.constructor = Child
var arzhChild1 = new Child('arzh1', '18')
arzhChild1.body.push('head1')
console.log(arzhChild1.name,arzhChild1.age) //arzh1 18
console.log(arzhChild1.body) //[ 'foot', 'hand', 'head1' ]
var arzhChild2 = new Child('arzh2', '20')
arzhChild2.body.push('head2')
console.log(arzhChild2.name,arzhChild2.age) //arzh2 20
console.log(arzhChild2.body) //[ 'foot', 'hand', 'head2' ]
複製代碼
優勢:ui
缺點:this
Child.prototype = new Parent()
,第二次是Parent.call(this, name)
形成沒必要要的浪費複製傳入的對象到建立對象的原型上,從而實現繼承spa
function createObj(o) {
function F(){}
F.prototype = o;
return new F();
}
var person = {
name : 'arzh',
body : ['foot','hand']
}
var person1 = createObj(person)
var person2 = createObj(person)
console.log(person1) //arzh
person1.body.push('head')
console.log(person2) //[ 'foot', 'hand', 'head' ]
複製代碼
缺點: 同原型鏈繼承同樣,每一個實例對引用類型屬性的修改都會被其餘的實例共享prototype
咱們可使用Object.create
來代替上述createObj
的實現,原理基本上是同樣的。寄生式繼承其實就是在createObj
的內部以某種形式來加強對象(這裏的加強能夠理解爲添加對象的方法),最後返回加強以後的對象。code
function createEnhanceObj(o) {
//代替原型式繼承的createObj
var clone = Object.create(o)
clone.getName = function () {
console.log('arzh')
}
return clone;
}
複製代碼
經過createEnhanceObj
就能夠在建立對象的時候,把對象方法也經過此種方式繼承。
缺點: 同借用構造函數同樣,沒法複用父類函數,每次建立對象都會建立一遍方法cdn
不須要爲了子類的原型而多new
了一次父類的構造函數,如Child.prototype = new Parent()
只須要複製父類原型的一個副本給子類原型便可
function inheritPrototype(Parent, Child){
Child.prototype = Object.create(Parent.prototype) //建立父類原型的一個副本,把副本賦值給子類原型
Child.prototype.constructor = Child;
}
function Parent(name) {
this.name = name
}
Parent.prototype.getName = function () {
console.log(this.name)
}
function Child(color) {
Parent.call(this, 'arzh')
this.color = color
}
inheritPrototype(Parent, Child)
var arzhChild = new Child('red')
console.log(arzhChild.name) // 'arzh'
複製代碼
優勢: 沒必要爲了指定子類型的原型而調用父類型的構造函數
ES6
支持經過類來實現繼承,方法比較簡單,代碼以下
class Point {
constructor(x, y) {
this.x = x
this.y = y
}
toString() {
return this.x + '' + this.y
}
}
class ColorPoint extends Point {
constructor(x, y, color) {
super(x, y) //調用父類的constructor(x, y)
this.color = color
}
toString() {
return this.color + ' ' + super.toString() // 調用父類的toString()
}
}
var colorPoint = new ColorPoint('1', '2', 'red')
console.log(colorPoint.toString()) // red 12
複製代碼
對本文有任何優化建議,可掃描下述二維碼一塊兒討論,同時也但願你們多多關注,會不按期發送一些原創文章