iT邦幫忙

1

Javascript 進階 6-3 使用建構式自定義原型

  • 分享至 

  • xImage
  •  

如何定義自己的原型

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

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

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 的這個運算子。

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

https://ithelp.ithome.com.tw/upload/images/20200227/201217707cCVFHIPav.png

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);

運行結果如下:

https://ithelp.ithome.com.tw/upload/images/20200227/20121770KgOdSyQZeu.png

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

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

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

https://ithelp.ithome.com.tw/upload/images/20200227/20121770ugsjOsbuyL.png

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

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

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

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

https://ithelp.ithome.com.tw/upload/images/20200227/20121770jUuMrX9BRS.png

透過 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);

https://ithelp.ithome.com.tw/upload/images/20200227/20121770NZ3S37Teca.png

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

那麼我們就實際的來吼叫看看!!

Bibi.bark();
Pupu.bark();

https://ithelp.ithome.com.tw/upload/images/20200227/20121770TLjIEz3jFu.png

好~到這邊我們來總結一下,Dog 這個函式又被稱為建構函式,用於建構其他實體所用的。

而為什麼我們需要把 bark 的方法掛載在 Dog 的 prototype上呢? 主要是因為如果一直撰寫在不同的物件中,會消耗記憶體的容量,當你需要記載的函式越來越多的時候,記憶體的負擔就會更大。

所以透過統一掛載在 Dog 的 prototype上,可以提高效率,也方便作修改,一次只要調整一個地方就好,對於程式碼來說也是很好維護的做法。

那麼在這邊在說明一件事,上一篇文章我們是直接將方法掛載在 proto 的屬性上,但其實這個屬性是用來指向該物件的原型是誰的一個屬性。

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

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

這樣的方法會比較好喔!

雖然呢

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

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

今天就先這樣啦~希望這篇文章對大家有幫助~汪汪!


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言