0%

JS核心-(47)-繼承與原型練-使用建構式自定義原型

前言

如何定義自己的原型

定義自己的原型

在這邊我們定義了兩個物件,等等我們會用建構式的方式產生這兩個物件,並且這兩個物件繼承同一個原型。

情境跟上一篇文章一樣,我們是造物主,我們必須在腦海中先有狗的原型,然後創造出兩隻狗,一隻叫比比,一隻叫噗噗。

var Bibi = {
    name: '比比',
    color: '棕色',
    size: '小',
    bark: function () {
        console.log(this.name + '吠叫');
    }
};

var Pupu = {
    name: '噗噗',
    color: '白色',
    size: '大',
    bark: function () {
        console.log(this.name + '吠叫');
    }
};

這兩隻狗都具有吠叫的方法,也就是說這個方法我們可以定義在這兩隻狗的藍圖上,也就是他們的原型函式。

我們在定義屬性的時候,會利用 this.屬性名稱 = 屬性 的方式定義,這樣在使用 new 的時候就可以客製化的傳入並賦予不同的

屬性內容。

function Dog (name, color, size) {
    this.name = name;
    this.color = color;
    this.size = size;
}

現在 Dog 的函式只是一個藍圖,它並不是一個實體,要讓它變成實體我們就需要使用到 new 的這個運算子。

首先我們先來看一下這個運算子的 相關文件

MDN 文件提到,使用 new 運算子會產生一個 Javascript 的物件,並且會連結回原本的物件(在這邊的例子也就是指說被 new 出來的實體會連結到原本的 Dog 的函式)。另外也會把 this 指向到新產生的實體上。

我們實際做做看 ~

function Dog (name, color, size) {
    this.name = name;
    this.color = color;
    this.size = size;
}

var Bibi = new Dog('比比','棕色', '小');
console.log('Bibi', Bibi);

運行結果:

可以看到印出來之後,展開 Bibi__proto__ 之後,其中的 constructor 屬性指向了 Dog 的函式,代表這個物件是由 Dog 這個函示所創建的。

再來我們一樣創建噗噗這隻狗

var Pupu = new Dog('噗噗','白色', '大');
console.log('Pupu', Pupu);

運行結果:

現在我們兩隻狗都創建出來了,但是你會發現還少了吠叫的方法。

這時候就要用我們上一篇文章提到的 prototype 的方法將共用的函式方法掛載到原型上,也就是 Dog 的原型。


首先我們先 console.dir(Dog); 觀察一下狗這個函式,我們之前也有說過,函示本身就是一個物件。

所以函式裡面有一個通用的屬性叫做 prototype

透過 prototype 所新增的方法,就會作為原型上的屬性,可以被向下的其他原型或是實體給取用到。

所以我們就透過將 bark 這個函式掛載在 Dog 這個原型的 prototype 上:

function Dog (name, color, size) {
    this.name = name;
    this.color = color;
    this.size = size;
}

// 多了這裡喔!!!!!!!
Dog.prototype.bark = function () {
    console.log(this.name + '吠叫');
}
// 多了這裡喔!!!!!!!

var Bibi = new Dog('比比','棕色', '小');
console.log('Bibi', Bibi);

var Pupu = new Dog('噗噗','白色', '大');
console.log('Pupu', Pupu);

之後點開來看,這兩隻狗都可以找到 bark 的吼叫功能。

我們就實際呼叫看看!

Bibi.bark();  // 比比吠叫
Pupu.bark();  // 噗噗吠叫

總結

Dog 這個函式又被稱為建構函式,用於建構其他實體所用的。

為什麼我們需要把 bark 的方法掛載在 Dogprototype上呢 ? 主要是因為如果一直撰寫在不同的物件中,會消耗記憶體的容

量,當你需要記載的函式越來越多的時候,記憶體的負擔就會更大。所以透過統一掛載在 Dogprototype 上,可以提高效

率,也方便作修改,一次只要調整一個地方就好,對於程式碼來說也是很好維護的做法。


注意!上一篇文章我們是直接將方法掛載在 __proto__ 的屬性上,但其實這個屬性是用來指向該物件的原型是誰的一個屬性。

如果我們要將共用的函式掛載在原型上的話,最好還是使用 ↓

建構函式名稱.prototype.共用函式名稱 = function (params) {
    ...
}

雖然

console.log(Dog.prototype === Bibi.__proto__); // true

這樣兩個內容是一樣的,但還是希望大家使用 prototype 去掛載需要用到的共用函式,同時你在除錯的時候,也比較容易找到

問題點在哪裡!