JS繼續

媒介

JS作為面向對象的弱範例言語,繼續也是其異常壯大的特徵之一。那末如安在JS中完成繼續呢?讓我們拭目以待。

JS繼續的完成體式格局

既然要完成繼續,那末起首我們得有一個父類,代碼以下:

 // 定義一個動物類
    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、原型鏈繼續

中心: 將父類的實例作為子類的原型

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

特性:
異常地道的繼續關聯,實例是子類的實例,也是父類的實例
父類新增原型要領/原型屬性,子類都能訪問到
簡樸,易於完成

瑕玷:
能夠在Cat組織函數中,為Cat實例增添實例屬性。假如要新增原型屬性和要領,則必需放在new Animal()如許的語句以後實行。
沒法完成多繼續
來自原型對象的援用屬性是一切實例同享的。(細緻請看附錄代碼:示例1)
建立子類實例時,沒法向父類組織函數傳參
引薦指數:★★(3、4兩大致命缺點)

2、組織繼續

中心:運用父類的組織函數來加強子類實例,等於是複製父類的實例屬性給子類(沒用到原型)

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

長處:
處理了1中,子類實例同享父類援用屬性的題目
建立子類實例時,能夠向父類通報參數
能夠完成多繼續(call多個父類對象)

瑕玷:
實例並非父類的實例,只是子類的實例
只能繼續父類的實例屬性和要領,不能繼續原型屬性/要領
沒法完成函數復用,每一個子類都有父類實例函數的副本,影響機能
引薦指數:★★(瑕玷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

特性:
不限定挪用體式格局,不管是new 子類()照樣子類(),返回的對象具有雷同的結果

瑕玷:
實例是父類的實例,不是子類的實例
不支撐多繼續
引薦指數:★★

4、拷貝繼續

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

特性:
支撐多繼續

瑕玷:
效力較低,內存佔用高(由於要拷貝父類的屬性)
沒法獵取父類不可枚舉的要領(不可枚舉要領,不能運用for in 訪問到)
引薦指數:★(瑕玷1)

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

特性:
彌補了體式格局2的缺點,能夠繼續實例屬性/要領,也能夠繼續原型屬性/要領
既是子類的實例,也是父類的實例
不存在援用屬性同享題目
可傳參
函數可復用

瑕玷:
挪用了兩次父類組織函數,生成了兩份實例(子類實例將子類原型上的那份屏障了)

引薦指數:★★★★(僅僅多斲喪了一點內存)

6、寄生組合繼續
中心:經由歷程寄生體式格局,砍掉父類的實例屬性,如許,在挪用兩次父類的組織的時刻,就不會初始化兩次實例要領/屬性,防止的組合繼續的瑕玷

function Cat(name){
  Animal.call(this);
  this.name = name || 'Tom';
}
(function(){
  // 建立一個沒有實例要領的類
  var Super = function(){};
  Super.prototype = Animal.prototype;
  //將實例作為子類的原型
  Cat.prototype = new Super();
})();

// 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
該完成沒有修復constructor。
Cat.prototype.constructor = Cat; // 須要修復下組織函數

特性:
可謂圓滿

瑕玷:
完成較為龐雜

引薦指數:★★★★(完成龐雜,扣掉一顆星)

附錄代碼:

示例一:

function Animal (name) {
  // 屬性
  this.name = name || 'Animal';
  // 實例要領
  this.sleep = function(){
    console.log(this.name + '正在睡覺!');
  }
  //實例援用屬性
  this.features = [];
}
function Cat(name){
}
Cat.prototype = new Animal();

var tom = new Cat('Tom');
var kissy = new Cat('Kissy');

console.log(tom.name); // "Animal"
console.log(kissy.name); // "Animal"
console.log(tom.features); // []
console.log(kissy.features); // []

tom.name = 'Tom-New Name';
tom.features.push('eat');

//針對父類實例值範例成員的變動,不影響
console.log(tom.name); // "Tom-New Name"
console.log(kissy.name); // "Animal"
//針對父類實例援用範例成員的變動,會經由歷程影響其他子類實例
console.log(tom.features); // ['eat']
console.log(kissy.features); // ['eat']

緣由剖析:

癥結點:屬性查找歷程

實行tom.features.push,起首找tom對象的實例屬性(找不到),
那末去原型對象中找,也就是Animal的實例。發現有,那末就直接在這個對象的
features屬性中插進去值。
在console.log(kissy.features); 的時刻。同上,kissy實例上沒有,那末去原型上找。
恰好原型上有,就直接返回,然則注重,這個原型對象中features屬性值已變化了。

    原文作者:逸心丿
    原文地址: https://segmentfault.com/a/1190000015130869
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞