JavaScript 核心觀念(49)- 繼承與原型鍊 - 使用建構式自定義原型

前言

接下來將會介紹使用原型練的建構式來自定義一個屬於自己的原型。

使用建構式自定義原型

首先底下這邊有兩個物件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var bibi = {
name: '比比',
color: '棕色',
size: '小',
bark: function() {
console.log(this.name + ' 吠叫');
}
}

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

接下來將會透過建構式的方式來產生這兩個上方兩個物件,並且都會繼承相同的原型。

首先這兩個物件都是一隻狗,並且都有相同的屬性與方法,因此這邊我們會先宣告一個函式,而這個函式則會則會有狗的名字、顏色與體型

1
2
3
4
5
function Dog(name, color, size) {
this.name = name;
this.color = color;
this.size = size;
}

在這邊 this 是代表的是 Dog 本身,因此我們在實體也就是 new 時傳入給 Dog 本身的屬性,但是這邊我們可以看到我們並沒有將 bark 的方法給建立在建構式中。

這邊先來講講什麼是 new,在 MDN 文件中其實有說明這將會建立一個新的物件,而且你也可以看到 MDN 的範例也與上方雷同

1
2
3
4
5
6
7
8
9
10
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}

const car1 = new Car('Eagle', 'Talon TSi', 1993);

console.log(car1.make);
// expected output: "Eagle"

而在此剛剛所使用的 this 在 MDN 上也有說明

new 关键字会进行如下的操作:
创建一个空的简单JavaScript对象(即{});
链接该对象(设置该对象的constructor)到另一个对象 ;
将步骤1新创建的对象作为this的上下文 ;
如果该函数没有返回对象,则返回this。

接下來讓我們來使用 new 來將剛剛的 Bibi 與 Pupu 給叫回來

1
2
3
4
5
6
7
8
function Dog(name, color, size) {
this.name = name;
this.color = color;
this.size = size;
}

var bibi = new Dog('比比', '棕色', '小');
var pupu = new Dog('噗噗', '白色', '大');

透過這個方式我們就可以讓剛剛一大串的物件都繼承相同的屬性,並且也是一個物件

實體

那麼其實在往上一層看 __proto__,可以看到它就是透過 Dog 的建構式所建立的。

但是在目前的的原型中,我們並沒有看到原型方法,也就是 bark,那麼該怎麼加入呢?在此我們就必須使用 prototype,而這個 prototype 是原型物件特有的屬性,如果你要加入方法就必須使用 prototype

1
2
3
4
5
6
7
8
9
10
11
12
function Dog(name, color, size) {
this.name = name;
this.color = color;
this.size = size;
}

Dog.prototype.back = function() {
console.log(this.name + ' 吠叫');
}

var bibi = new Dog('比比', '棕色', '小');
var pupu = new Dog('噗噗', '白色', '大');

這樣子我們就可以透過 bibi.back() 來吠叫

吠叫

但是這邊要注意擺放 prototype 的地方是會影響是否可使用 back()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function Dog(name, color, size) {
this.name = name;
this.color = color;
this.size = size;
}

var bibi = new Dog('比比', '棕色', '小');
var pupu = new Dog('噗噗', '白色', '大');

bibi.back(); // is not function
pupu.back(); // is not function

Dog.prototype.back = function() {
console.log(this.name + ' 吠叫');
}

最後這邊補充一下前面有講到的 __proto__prototype 有什麼樣的不同,基本上可以這樣子區分

  • __proto__ 基於物件上建立
  • prototype 基於函式上建立

而在此所謂的物件,也就是原型的頂層物件,因此會建議是基於 Dog 的函式去建立,而在此也與前一個章節後面所補充的相同,會導致原型在追朔上較困難,而且使用 __proto__ 也會覆蓋掉原本使用 prototype 所建立的原型方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function Dog(name, color, size) {
this.name = name;
this.color = color;
this.size = size;
}

Dog.prototype.back = function() {
console.log(this.name + ' 吠叫');
}

var bibi = new Dog('比比', '棕色', '小');

bibi.back();

bibi.__proto__.back = function() {
console.log(this.name + ' 才不吠叫給你聽');
}

var pupu = new Dog('噗噗', '白色', '大');

pupu.back();

被覆蓋了

參考文獻

Liker 讚賞

這篇文章如果對你有幫助,你可以花 30 秒登入 LikeCoin 並點擊下方拍手按鈕(最多五下)免費支持與牡蠣鼓勵我。
或者你可以也可以請我「喝一杯咖啡(Donate)」。

Buy Me A Coffee Buy Me A Coffee

Google AD

撰寫一篇文章其實真的很花時間,如果你願意「關閉 Adblock (廣告阻擋器)」來支持我的話,我會非常感謝你 ヽ(・∀・)ノ