1. 程式人生 > >js中7種繼承的實現和優缺點

js中7種繼承的實現和優缺點

原型鏈 副本 obj 無法 line 衍生 組合 不存在 所有

原型鏈繼承

function Parent(){
    this.name = ‘kevin‘
}

Parent.prototype.getName = function(){
    console.log(this.name)
}

function Child(){

}
Child.prototype = new Parent()

var child = new Child()
console.log(child.name) //kevin

  

優點:

  1. 簡單,容易實現

缺點:

  1. 來自父類原型對象的引用屬性是所有子類實例共享的
  2. 創建子類實例時,無法向父類構造函數傳參

借用構造函數(經典繼承)

function Parent(name){
    this.name = name
}

function Child(name){
    Parent.call(this,name)
}

let child = new Child(‘Tom‘)
let child1 = new Child(‘Jack‘)
console.log(child.name) //Tom
console.log(child1.name) //Jack

  

優點:

  1. 解決了子類型實例共享父類引用屬性的問題
  2. 創建子類實例時,可以向父類構造函數傳參

缺點:

  1. 無法實現函數復用 ,方法在構造函數中定義,每次創建子類實例都會創建一個新方法,占用內存

組合繼承(原型鏈繼承和經典繼承的雙劍合璧)

function Parent(name){
    this.name = name
    this.color = [‘red‘,‘bule‘,‘green‘]
}

Parent.prototype.getName = function(){
    console.log(this,name)
}

function Child(name,age){
    this.age = age
    Parent.call(this,name)
}

Child.prototype = new Parent()
Child.prototype.constructor = Child
Child.prototype.getAge = function(){
    console.log(this.age)
}

let child = new Child(‘Tom‘,12)
console.log(child.name) //Tom
child.getAge()  //12
child.color.push(‘blcak‘)
console.log(child.color) //[‘red‘,‘bule‘,‘green‘,‘black‘]

let child1 = new Child(‘Jack‘,18)
console.log(child1.name) //Jack
child1.getAge()  //18
console.log(child1.color) //[‘red‘,‘bule‘,‘green‘]

  

優點:

  1. 不存在父類引用屬性共享問題
  2. 可以給父類構造函數傳參
  3. 通過原型屬性設置方法,使得函數可復用
  4. 最常用的繼承方式

缺點(小瑕疵):

  1. 子類調用了兩次父類構造函數,生成了兩個父類實例,第二次調用改變了指向第一個實例的指針,使得第一個實例變得多余了

原型式繼承

function object(o){ 
    function F(){}
    F.prototype = o
    return new F()
}

//在ES5中有了新方法代替Object.created(o,{name:‘Ton‘等新屬性})

let person = {
    name:‘Tom‘,
    color : [‘red‘,‘bule‘,‘green‘]
}

let person1 = Object.create(person)
let person2 = Object.create(person)

person1.name = ‘Jack‘
person1.color.push(‘black‘)
person2.name = ‘Kevin‘
person1.color.push(‘yellow‘)

console.log(person1.name)   //Jack
console.log(person2.name)   //Kevin
console.log(person1.color == person2.color)  //true

  

優點:

  1. 從已有對象衍生新對象,不需要創建自定義類型,更像是對象復制

缺點:

  1. 原型引用的屬性被實例所共享
  2. 無法實現代碼復用

寄生式繼承

let person = {
    name:‘Tom‘,
    color : [‘red‘,‘bule‘,‘green‘]
}

function createAnother(o){ 
    let clone = create(o)
    clone.getName(){
        console.log(this.name)
    }
    return clone    //clone這個對象不僅有原型引用屬性,還有自己的方法
}

let person1 = createAnother(person)
person1.getName() //Tom 

  

優點:

  1. 不需要創建自定義類型

缺點:

  1. 原型引用的屬性被實例所共享
  2. 無法實現代碼復用

##寄生組合式繼承(最佳方式)

function Parent (name) {
  this.name = name;
  this.colors = [‘red‘, ‘blue‘, ‘green‘];
}
 
Parent.prototype.getName = function () {
  console.log(this.name)
}
 
function Child (name, age) {
  Parent.call(this, name);
  this.age = age;
}

function prototype(Child,Parent){ //獲得父類型原型上的方法
    let prototype = object(Parent.prototype) //創建父類型原型的一個副本,相當於prototype.__proto__ = Parent.prototype
    prototype.constructor = Child
    Child.prototype = prototype
}

prototype(Child,Parent) //必須執行這個函數,才能進行給子類型原型寫方法,順序調轉的話子類型原型會被重寫
Child.prototype.getName = function(){
    console.log(this.name)
}

  

優點:完美 缺點:用起來麻煩

class繼承

class Parent {
    constructor(name,age){
        this.name = name
        this.age = age
    }
    showName(){
        console.log(this.name);
    }
}

class Child extends Parent{
    constructor(name,age,sex){
        super(name,age)
        this.sex = sex
    }
    showSex(){
        console.log(this.sex);
    }
}
let parent = new Parent(‘Jack‘,30)
console.log(parent.name,parent.age);
let child = new Child(‘Tom‘,12,‘男‘)
console.log(child.name,child.age);
child.showName() //Tom
child.showSex() //男

  

 

js中7種繼承的實現和優缺點