javascript繼承的幾種方式

原型鏈繼承bash

利用prototype將子構造函數的prototype指向Person達到繼承的目的函數

function Person(name){
    this.name = name;
    this.country='china';
}
Person.prototype.play = function(){
    
}

function Child(age){
    this.age = age;
}

Child.prototype = new Person();

複製代碼

缺點:ui

  • 建立子類實例時,可是沒法給父構造函數傳參
  • 來自原型對象的引用屬性是全部實例共享的

構造函數繼承this

在子類構造函數中借用call調用父類構造函數spa

function Person(name){
    this.name = name;
    this.country='china';
}
Person.prototype.play = function(){
    
}

function Child(name,age){
    this.age = age;
    Person.call(this,name)
}
var obj = new Child('小明',16);
複製代碼

優勢:prototype

  • 解決了子類構造函數向父類構造函數傳參數和實例共享原型屬性的問題

缺點:code

  • 至關於每一個實例都拷貝了一份父類的方法,佔用內存大
  • 不能繼承原型屬性/方法,只能繼承父類的實例屬性和方法

組合繼承對象

使用原型鏈實現對原型屬性和方法的繼承,經過借用構造函數實現對實例屬性的繼承繼承

function Person(name){
    this.name = name;
    this.country='china';
}
Person.prototype.play = function(){
    
}
function Child(name,age){
    Person.call(this,name);
    this.age = age;
}
Child.prototype = new Person();
複製代碼

缺點:遞歸

  • 會調用兩次父類構造函數

原型式繼承

基於已有對象,建立新對象

// 在object函數內部,先建立了一個臨時的構造函數,而後將傳入的對象做爲這個構造函數的原型,最後返回這個臨時類型的一個新實例。
// 從本質上講,object()對傳入其中的對象執行了一次淺複製。

function object (o) {
  function F() {}
  F.prototype = o;
  return new F();
}
缺點:
-  和原型鏈繼承同樣,全部子類實例共享父類的引用類型
複製代碼

寄生式繼承

寄生式繼承是與原型式繼承緊密相關的一種思路,建立一個僅用於封裝繼承過程的函數,該函數內部以某種形式來作加強對象,最後返回對象

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

function createAnother (o) {
  var clone = object(o);
  clone.sayHi = function () {
    console.log('Hi');
  }
  return clone;
}
缺點:
1,和原型鏈式繼承同樣,全部子類實例共享父類引用類型。
2,和借用構造函數繼承同樣,每次建立對象都會建立一次方法
複製代碼

寄生組合式繼承

結合組合式繼承和寄生式繼承,解決組合式繼承調用兩次父類構造函數的問題

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

function inheritPrototype(SubType, SuperType) {
  var prototype = object(SuperType.prototype);        // 建立對象
  prototype.constructor = SubType;    // 加強對象
  SubType.prototype = prototype;      // 指定對象 
}

// 父類
function SuperType(name) {
  this.name = name;
  this.colors = ["red", "blue", "green"];
}

SuperType.prototype.sayName = function () {
  console.log(this.name);
};

// 子類
function SubType(name, age) {
  // 繼承父類實例屬性
  SuperType.call(this, name);

  // 子類實例屬性
  this.age = age;
}

// 繼承父類方法
inheritPrototype(SubType, SuperType);
複製代碼

Es6繼承

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

function inheritPrototype(SubType, SuperType) {
  var prototype = object(SuperType.prototype);        // 建立對象
  prototype.constructor = SubType;    // 加強對象
  SubType.prototype = prototype;      // 指定對象 
}

// 父類
function SuperType(name) {
  this.name = name;
  this.colors = ["red", "blue", "green"];
}

SuperType.prototype.sayName = function () {
  console.log(this.name);
};

// 子類
function SubType(name, age) {
  // 繼承父類實例屬性
  SuperType.call(this, name);

  // 子類實例屬性
  this.age = age;
}

// 繼承父類方法
inheritPrototype(SubType, SuperType);

`底層也是用寄生組合式繼承實現的`
複製代碼

拷貝繼承 把一個對象中的屬性和方法複製到另外一個

淺拷貝
 function shallowCopy(source, target = {}) {
        var key;
        for (key in source) {
            if (source.hasOwnProperty(key)) {        // 意思就是__proto__上面的屬性,我不拷貝
                target[key] = source[key];
            }
        }
        return target;
    }

複製代碼
深拷貝 
(對象裏面嵌套對象才涉及深拷貝)
function deepCopy(source, target = {}) {
        var key;
        for (key in source) {
            if (source.hasOwnProperty(key)) {                         // 意思就是__proto__上面的屬性,我不拷貝
                if (typeof(source[key]) === "object") {               // 若是這一項是object類型,就遞歸調用deepCopy
                    target[key] = Array.isArray(source[key]) ? [] : {};
                    deepCopy(source[key], target[key]);
                } else {                                            // 若是不是object類型,就直接賦值拷貝
                    target[key] = source[key];
                }
            }
複製代碼

深拷貝黑科技

var targetObj = JSON.parse(JSON.stringify(copyObj))

缺點:
一、若是你的對象裏有函數,函數沒法被拷貝下來
二、沒法拷貝copyObj對象原型鏈上的屬性和方法
複製代碼
相關文章
相關標籤/搜索