JavaScript對象繼承方式

一、對象冒充

其原理如下:構造函數使用 this 關鍵字給所有屬性和方法賦值(即採用類聲明的構造函數方式)。因爲構造函數只是一個函數,所以可使 Parent 構造函數 成爲 Children 的方法,然後調用它。Children 就會收到 Parent 的構造函數中定義的屬性和方法。例如,用下面的方式定義 Parent 和 Children:

]// 父類構造函數
var Parent = function(name){
    this.name = name;

    this.sayHi = function(){
        console.log("Hi! " + this.name + ".");
    }//前端全棧學習交流圈:866109386
};//面向1-3年前端人員
//幫助突破技術瓶頸,提升思維能力
// 子類構造函數
var Children = function(name){
    this.method = Parent;
    this.method(name); // 實現繼承的關鍵
    delete this.method;

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

var p = new Parent("john");
var c = new Children("joe");

p.sayHi(); // 輸出: Hi! john.
c.sayHi(); // 輸出: Hi! joe.
c.getName(); // 輸出: jo

原理:就是把 Parent 構造函數放到 Children 構造函數裏面執行一次。那爲什麼不直接執行,非要轉個彎把 Parent 賦值給 Children 的 method 屬性再執行呢? 這跟 this 的指向有關,在函數內 this 是指向 window 的。當將 Parent 賦值給 Children 的 method 時, this 就指向了 Children 類的實例。

二、原型鏈繼承

衆所周知,JavaScript 是一門基於原型的語言,在 JavaScript 中 prototype 對象的任何屬性和方法都被傳遞給那個類的所有實例。原型鏈利用這種功能來實現繼承機制:

// 父類構造函數
var Parent = function(){
    this.name = "john";

    this.sayHi = function(){
        console.log("Hi! " + this.name + ".");
    }
};

// 子類構造函數
var Children = function(){};

Children.prototype = new Parent(); // 實現繼承的關鍵

var p = new Parent();
var c = new Children();

p.sayHi(); // 輸出: Hi! john.
c.sayHi(); // 輸出: Hi! john.

注意:調用 Parent 的構造函數,沒有給它傳遞參數。這在原型鏈中是標準做法。要確保構造函數沒有任何參數。

三、使用 call 或 applay 方法

這個方法是與對象冒充方法最相似的方法,因爲它也是通過改變了 this 的指向而實現繼承:

// 父類構造函數
var Parent = function(name){
    this.name = name;

    this.sayHi = function(){
        console.log("Hi! " + this.name + ".");
    }
};

// 子類構造函數
var Children = function(name){
    Parent.call(this, name); // 實現繼承的關鍵

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

var p = new Parent("john");
var c = new Children("joe");

p.sayHi(); // 輸出: Hi! john.
c.sayHi(); // 輸出: Hi! john.
c.getName(); // 輸出: joe

apply 方法本人就不舉列了,它和 call 方法的區別在於它的第二個參數必須是數組。

四、混合方式

對象冒充的主要問題是必須使用構造函數方式,這不是最好的選擇。不過如果使用原型鏈,就無法使用帶參數的構造函數了。如何選擇呢?答案很簡單,兩者都用。 在 JavaScript 中創建類的最好方式是用構造函數定義屬性,用原型定義方法。這種方式同樣適用於繼承機制:

// 父類構造函數
var Parent = function(name){
    this.name = name;
};

Parent.prototype.sayHi = function(){
    console.log("Hi! " + this.name + ".");
};

// 子類構造函數
var Children = function(name, age){
    Parent.call(this, name); // 實現繼承的關鍵
    this.age = age;
};

Children.prototype = new Parent(); // 實現繼承的關鍵

Children.prototype.getAge = function(){
    console.log(this.age);
};//前端全棧開發交流圈:866109386
//幫助1-3年前端人員突破技術瓶頸,提升思維
var p = new Parent("john");
var c = new Children("joe",30);

p.sayHi(); // 輸出: Hi! john.
c.sayHi(); // 輸出: Hi! joe.
c.getAge(); // 輸出: 30

五、使用Object.create 方法

Object.create 方法會使用指定的原型對象及其屬性去創建一個新的對象:

// 父類構造函數
var Parent = function(name){
    this.name = name;
};

Parent.prototype.sayHi = function(){
    console.log("Hi! " + this.name + ".");
};

// 子類構造函數
var Children = function(name, age){
    Parent.call(this, name); // 實現繼承的關鍵
    this.age = age;
};

Children.prototype = Object.create(Parent.prototype); // 實現繼承的關鍵
Children.prototype.constructor = children; // @

Children.prototype.getAge = function(){
    console.log(this.age);
};

var p = new Parent("john");
var c = new Children("joe",30);

p.sayHi(); // 輸出: Hi! john.
c.sayHi(); // 輸出: Hi! joe.
c.getAge(); // 輸出: 30

@ 當執行 Children.prototype = Object.create(Parent.prototype) 這個語句後,Children 的 constructor 就被改變爲 Parent ,因此需要將 Children.prototype.constructor 重 新指定爲 Children 自身。

六、extends 關鍵字實現繼承

這個是 ES6 的語法糖,下面看下es6實現繼承的方法:

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

class Children extends Parent {
  constructor(name, age, job) {
    this.job = job; // 這裏會報錯
    super(name, age);
    this.job = job; // 正確
  }
}

上面代碼中,子類的constructor方法沒有調用super之前,就使用this關鍵字,結果報錯,而放在super方法之後就是正確的。子類Children的構造函數之中的super(),代表調用父類Parent的構造函數。這是必須的,否則 JavaScript 引擎會報錯。

注意,super雖然代表了父類Parent的構造函數,但是返回的是子類Children的實例,即super內部的this指的是Children,因此super()在這裏相當於Parent.prototype.constructor.call(this)。


本文來自雲棲社區合作伙伴“開源中國”

本文作者:peakedness

原文鏈接

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章