JS實現繼承 JavaScript

JS實現繼承 JavaScript

定義一個父類:

// 定義一個動物類
function Animal (name) {
// 屬性
this.name = name || ‘Animal’;
// 實例方法
this.sleep = function(){
console.log(this.name + ‘正在睡覺!’);
}
}
// 原型方法
Animal.prototype.eat = function(food) {
console.log(this.name + ‘正在吃:’ + food);
};

1.原型鏈繼承

核心:將父類的實例做爲子類的原型, JavaScript常見的六種繼承方式
function Cat(){
}
Cat.prototype = new Animal();
Cat.prototype.name = ‘cat’;

// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.eat(‘fish’));
console.log(cat.sleep());
console.log(cat instanceof Animal); //true
console.log(cat instanceof Cat); //true

特色:html

  1. 很是純粹的繼承關係,實例是子類的實例,也是父類的實例
  2. 父類新增的原型方法、屬性,子類都能訪問到
  3. 簡單,易於實現

缺點:es6

  1. 要想爲子類新增屬性和方法,必需要在new Animal()這樣的語句以後執行(能夠在cat構造函數中,爲Cat實例增長實例屬性)
  2. 沒法實現多繼承
  3. 來自原型對象的引用屬性被全部實例共享
  4. 建立子類實例時,沒法向父類構造函數傳參

下面代碼解釋缺點3(注意是引用屬性):segmentfault

function Super(){
    this.val = 1;
    this.arr = [1];
}
function Sub(){
    // ...
}
Sub.prototype = new Super();    // 核心
 
var sub1 = new Sub();
var sub2 = new Sub();
sub1.val = 2;
sub1.arr.push(2);
alert(sub1.val);    // 2
alert(sub2.val);    // 1
 
alert(sub1.arr);    // 1, 2
alert(sub2.arr);    // 1, 2

2.構造繼承

核心:使用父類的構建函數來加強子類實例,等於複製父類的實例屬性給子類(沒用到原型),除了call方法,也能夠用apply()
function Cat(name){
Animal.call(this);
this.name = name || ‘Tom’;
}

// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true

特色:app

  1. 解決了1中,子類實例共享父類引用屬性的問題
  2. 建立子類實例時,能夠向父類傳遞參數
  3. 能夠實現多繼承(call多個父類對象)

缺點:函數

  1. 實例並非父類的實例,只是子類的實例
  2. 只能繼承父類的實例屬性和方法,不能繼承原型屬性和方法
  3. 沒法實現函數複用,每一個子類都有父類的實例函數的副本,影響性能

3.實例繼承

核心:爲父類實例添加新特性,做爲子類實例返回
function Cat(name){
var instance = new Animal();
instance.name = name || ‘Tom’;
return instance;
}

// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); // false

特色:性能

  1. 不限制調用方式,無論是new 子類()仍是子類(),返回的對象都具備相同的效果

缺點:this

  1. 實例是父類的實例,不是子類的實例
  2. 不支持多繼承

4. 拷貝繼承

核心:使用for...in將父類實例中的方法賦給子類實例
function Cat(name){
var animal = new Animal();
for(var p in animal){
Cat.prototype[p] = animal[p];
}
Cat.prototype.name = name || ‘Tom’;
}

// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true

特色:prototype

  1. 支持多繼承

缺點:code

  1. 效率較低,內存佔用高(由於要拷貝父類的屬性)
  2. 沒法獲取父類不可枚舉的方法(for in沒法訪問不可枚舉的方法)

5.組合繼承

核心:經過調用父類構造,繼承父類的屬性並保留傳參的優勢,而後經過將父類實例做爲子類原型,實現函數複用
function Cat(name){
Animal.call(this);
this.name = name || ‘Tom’;
}
Cat.prototype = new Animal();

//組合繼承須要修復構造函數的指向
Cat.prototype.constructor=Cat;
// Test Code 

var cat = new Cat(); 
console.log(cat.name); 
console.log(cat.sleep()); 
console.log(cat instanceof Animal); // true 
console.log(cat instanceof Cat); // true

特色:htm

  1. 彌補了方式2的缺陷,能夠繼承實例屬性、方法,也能夠繼承原型屬性、方法
  2. 既是子類的實例,也是父類的實例
  3. 不存在引用屬性的共享問題
  4. 可傳參
  5. 函數可複用

缺點:

  1. 調用了兩次父類構造函數,生成了兩份實例(子類實例將子類原型上的那份屏蔽了)

6.寄生組合繼承

核心:經過寄生方式,砍掉父類的實例屬性,這樣,在調用兩次父類的構造的時候,就不會初始化兩次實例方法/屬性,避免的組合繼承的缺點
function Cat(name){
Animal.call(this);
this.name = name || ‘Tom’;
}
(function(){
// 建立一個沒有實例方法的類
var Super = function(){};
Super.prototype = Animal.prototype;
//將實例做爲子類的原型
Cat.prototype = new Super();
//寄生組合繼承須要修復構造函數的指向
Cat.prototype.constructor=Cat;
})(); 

// Test Code 

var cat = new Cat(); 
console.log(cat.name); 
console.log(cat.sleep()); 
console.log(cat instanceof Animal); // true 
console.log(cat instanceof Cat); //true

特色:

  1. 堪稱完美

缺點:

  1. 實現較爲複雜

補充:es6的class實現繼承

class Animal {
    //構造函數
    constructor(props) {
      this.name = props.name || '未知';
    }

    eat() {
      alert(this.name + "在吃東西...");
    }
  }

  //class繼承
  class Bird extends Animal {
    //構造函數
    constructor(props) {
      //調用實現父類的構造函數
      super(props);
      this.name = props.name || "未知";
    }

    fly() {
      alert(this.name + "在飛...");
    }
  }
  var myBird = new Bird({
    name: '鸚鵡'
  })
  myBird.eat()  // 鸚鵡在吃東西...
  myBird.fly()  // 鸚鵡在飛...

在這裏插入圖片描述

來源:https://segmentfault.com/a/1190000017935023

相關文章
相關標籤/搜索