iT邦幫忙

2023 iThome 鐵人賽

DAY 13
0

build-in object就是js自帶的建構函式

我們在新增物件、陣列時,有時會像下面這樣寫,其實就是使用js天生自帶的各種建構函式來建立各式各樣的衍生物件

const arr = new Array();
const obj = new Object();
console.log(arr);


看看MDN的分類,裡面有一些也許我們早就用過很多次,也有一些尚待我們去開發使用的標準內建物件。

自定建構函式,並由此新建衍生物件

由上面的例子我們發現兩個關鍵的東西,一個是建構函式(現在要由我們自訂),另一個是new這個運算子。

  • 建構函式裡定義屬性和方法,讓衍生的物件能夠參照
  • new運算子則是做下面幾件事
    • 建立一個空物件,為了方便起見,我們暫且稱它newInstance
    • 將newInstance的this指向本身
    • 將newInstance的[[prototype]]與建構函式的prototype屬性連結起來
    • 執行建構函式內容
    • 若建構函式沒有回傳東西,則回傳newInstance

看一個例子,利用建構函式Person來建立幾個擁有相同屬性(但屬性內容可客製化)的物件

const Person = function (firstName, birthYear) {
  this.firstName = firstName;
  this.birthYear = birthYear;
};

const john = new Person("John", 1990);
const sarah = new Person("Sarah", 1995);
console.log(john);
console.log(sarah);

衍生物件從哪邊關連到所謂的prototype?

上面的建構函式只包含建立屬性的部份,那如果建立的物件想包含方法,也可以這樣做嗎?由執行結果可以發現,calcAge這個方法在每個衍生物件中都被宣告一次,那如果我們用這個建構函式建了很多個物件,這段程式就會被重複宣告好多次。

onst Person = function (firstName, birthYear) {
  this.firstName = firstName;
  this.birthYear = birthYear;
  this.calcAge = function () {
    return 2023 - this.birthYear;
  };
};

const john = new Person("John", 1990);
const sarah = new Person("Sarah", 1995);
console.log(john);
console.log(sarah);

但利用prototypal inheritance的概念,可以把這個方法寫在建構函式的prototype屬性中,藉由剛剛new已經在衍生物件及建構函式之間建立了關係,可以藉此取用這個方法,而不用重複宣告。
哇塞..

Person.prototype.calcAge = function () {
  return 2023 - this.birthYear;
};

before

after

然後我們再重新建立兩個衍生物件:john & sarah,兩個物件內沒有看到重複宣告的方法,但可以使用方法喔!

const Person = function (firstName, birthYear) {
  this.firstName = firstName;
  this.birthYear = birthYear;
};

Person.prototype.calcAge = function () {
  return 2023 - this.birthYear;
};

const john = new Person("John", 1990);
const sarah = new Person("Sarah", 1995);
console.log(john);
console.log(sarah);
console.log(john.calcAge()); 
console.log(sarah.calcAge()); 

點開[[prototype]]看,能發現它們由建構函式那邊繼承過來的方法,而這個[[prototype]],我們將它視為john和sarah的prototype。

今日總結

其實自己有個好奇的問題是,方法可以寫在建構函式的prototype屬性,那屬性可以嗎?還真的可以,但這個繼承來的屬性就大家都一樣了,可以跟[[prototype]]中另一個屬性Constructor比較看看。

const Person = function (firstName, birthYear) {
  this.firstName = firstName;
  this.birthYear = birthYear;
};

Person.prototype.calcAge = function () {
  return 2023 - this.birthYear;
};
Person.prototype.job = "Engineer";

const john = new Person("John", 1990);
console.log(john);
console.log(john.job);

最後就是,其實這樣prototype的想法還蠻巧妙的,讓人眼睛一亮!

tl;dr
衍生物件(instance)的prototype=建構函式的prtototype屬性

Reference

MDN-new
udemy-The Complete Javascript Course


上一篇
物件導向概念
下一篇
js的OOP:ES 6 class & Object.create()
系列文
超低腦容量學習法遇到javascript30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言