我們在新增物件、陣列時,有時會像下面這樣寫,其實就是使用js天生自帶的各種建構函式來建立各式各樣的衍生物件
const arr = new Array();
const obj = new Object();
console.log(arr);
看看MDN的分類,裡面有一些也許我們早就用過很多次,也有一些尚待我們去開發使用的標準內建物件。
由上面的例子我們發現兩個關鍵的東西,一個是建構函式(現在要由我們自訂),另一個是new這個運算子。
[[prototype]]
與建構函式的prototype屬性
連結起來看一個例子,利用建構函式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);
上面的建構函式只包含建立屬性的部份,那如果建立的物件想包含方法,也可以這樣做嗎?由執行結果可以發現,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屬性
MDN-new
udemy-The Complete Javascript Course