首頁 >web前端 >js教程 >JS中原型式和寄生式繼承的詳解(程式碼範例)

JS中原型式和寄生式繼承的詳解(程式碼範例)

不言
不言轉載
2018-10-24 17:47:361997瀏覽

這篇文章帶給大家的內容是關於JS中原型式和寄生式繼承的詳解(程式碼範例),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

前言:最近在細讀Javascript高階程式設計,對我而言,中文版,書中很多地方翻譯的差強人意,所以用自己所理解的,試著解讀下。如有紕漏或錯誤,會非常感謝您的指出。文中絕大部分內容引用自《JavaScript高級程式設計第三版》。

原型式繼承

道格拉斯 克勞福德在2006年寫了一篇文章,題為Prototypal Inhertitance in JavaScript(JavaScript中的原型式繼承)。

在這篇文章中,他介紹了一種實作繼承的方法,這種方法並沒有使用嚴格意義上的建構子。

他的想法是藉助原型可以基於現有的對象創建新對象,同時還不必因此創建自訂類型。

為了達到這個目的,他給瞭如下函數。

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

在object()函數內部,先建立一個臨時性的建構函數,然後將傳入的物件作為這個建構函數的原型,最後傳回了這個臨時型別的一個新實例物件。

從本質上講,object()對傳入的物件執行了一次淺複製。

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

var person = {
    name: "Shaw",
    friends: ["Sharon", "Sandy", "Van"]
}

var person1 = object(person);

/*
person1 = function object(person){
    function F(){};
    F.prototype = person1;
    return new F();
}()

person1 = function object({
    name: "Shaw",
    friends: ["Sharon", "Sandy", "Van"]
}){
    function F(){};
    F.prototype = {
        name: "Shaw",
        friends: ["Sharon", "Sandy", "Van"]
    }
    return {
    }
}

person1 = {

};

{}.__proto__ = {
    name: "Shaw",
    friends: ["Sharon", "Sandy", "Van"]
}
*/

person1.name = "Roc";
person1.friends.push("Roster");

var person2 = object(person);

person2.name = "Linda";
person2.friends.push("Jobs");

console.log(person.friends); //["Sharon", "Sandy", "Van", "Roster", "Jobs"]
console.log(person1.friends); //["Sharon", "Sandy", "Van", "Roster", "Jobs"]
console.log(person2.friends); //["Sharon", "Sandy", "Van", "Roster", "Jobs"]

克羅克福德主張的這種原型式繼承,要求你必須有一個物件可以作為另一個物件的基礎。

如果有這麼一個物件的話,可以把它傳給object()函數,然後再根據具體需求對得到的物件加以修改即可。

ECMAscript5透過新增Object.create()方法規範了原型式繼承。
這個方法接收兩個參數: 一個用作新物件原型的物件和(可選的)一個為新物件定義額外屬性的物件。

在傳入一個參數的情況下,Object.create()與object()方法的行為相同。

var person = {
    name: "Shaw",
    friends: ["Sharon", "Sandy", "Van"]
}

var person1 = Object.create(person);
person1.name = "Roc";
person1.friends.push("Roster");

var person2 = Object.create(person);
person2.name = "Linda";
person2.friends.push("Messi");

console.log(person.friends); //["Sharon", "Sandy", "Van", "Roster", "Messi"]
console.log(person1.friends); //["Sharon", "Sandy", "Van", "Roster", "Messi"]
console.log(person2.friends); //["Sharon", "Sandy", "Van", "Roster", "Messi"]

Object.create()方法的第二個參數與Object.defienProperties()方法的第二個參數格式相同:

每個屬性都是透過自己的描述子定義的。

以這種方式指定的任何屬性都會覆寫原型物件上的同名屬性。

var person = {
    name: "Shaw",
    friends: ["Sharon", "Sandy", "Selina"]
}

var person1 = Object.create(person, {
    name: {
        value: "Roc"
    }
})

console.log(person1.name); //"Roc"

支援Object.create()方法的瀏覽器有IE9 , Firefox 4 , Opera 12 和 Chrome。

適用場景:

在沒有必要興師動眾地創建建構函數,而只想讓一個物件與另一個物件保持類似的情況下,原型繼承是完全可以勝任的。

千萬要記住,包含引用類型值的屬性總是會共用對應的值,就像使用原型模式一樣。

寄生式繼承

寄生式(parasitic)繼承是與原型式繼承緊密相關的一種思路,並且也是由大神克勞克福推而廣之的。

寄生式繼承的想法與寄生建構子和工廠模式類似。

創建一個僅用於封裝繼承過程的函數,該函數在內部以某種方式來增強對象,最後再像真地是它做了所有工作一樣返回對象。

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

function createAnother(original) {
    var clone = object(original); //通过调用函数创建一个新对象
    clone.sayHi = function(){ //以某种方式来增强这个对象
        console.log("hi");
    }
    return clone; //返回这个对象
}

在這個例子中, createAnother()函數接收了換一個參數,也就是將要作為新物件基礎的物件。
然後,把這個物件參數(original)傳遞給object()函數, 將傳回的結果賦值給clone。

再為clone物件新增一個新方法sayHi(),最後回傳clone物件。

可以像下面這樣來使用createAnother()函數:

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

function createAnother(original) {
    var clone = object(original); //通过调用函数创建一个新对象
    clone.sayHi = function(){ //以某种方式来增强这个对象
        console.log("hi");
    }
    return clone; //返回这个对象
}

var person = {
    name: "Shaw",
    friends: ["Sandy", "Sharon", "Van"]
}

var anotherPerson = createAnother(person);

anotherPerson.sayHi(); //"hi"

這個範例中的程式碼是基於person傳回一個新物件-anotherPerson。新物件不僅具有person的所有屬性和方法,而且還有自己的sayHi()方法。

在主要考慮物件而不是自訂類型和建構函數的情況下,寄生式繼承也是一種有用的模式。

前面示範繼承模式時使用的object()函數不是必需的,任何能夠傳回新物件的函數都適用於此模式。


以上是JS中原型式和寄生式繼承的詳解(程式碼範例)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除