JavaScript 核心觀念(50)- 繼承與原型鍊 - 原始型別的包裹物件與原型的關聯

前言

接下來將會介紹純值與包裹物件的關係,這兩者其實如果能釐清,也能夠大大減少遇到 Bug 的機會。

原始型別的包裹物件與原型的關聯

首先先講講一般的純值,我們在宣告純值時,都是這樣子

1
2
var myName = 'ray';
console.log(myName); // ray

而這個變數在瀏覽器 console 上就會是單純的黑體文字(懶得截圖),而在此若我們想要讓上方變數的純值變成全部大寫,那麼就可以使用 String (字串)的包裹物件方法來轉換成全大寫

1
2
var myName = 'ray';
console.log(myName.toUpperCase()); // RAY

除了我們常見的宣告方式之外,另一種宣告方式則是前面一直有強調說明的「使用包裹物件宣告的變數是不同的型別以及呈現方式」,因此這邊只是一個示範,實際開發時請不要這樣子宣告。

1
2
var myName = new String('ray');
console.log(myName.toUpperCase()); // RAY

上次可以看到結果是一樣的,雖然這種宣告方式是一個物件而不是 Strgin 型別

1
2
3
var myName = new String('ray');
console.log(myName.toUpperCase()); // RAY
typeof(myName); // object

但是透過這個方式,我們可以看到包裹物件所有可以使用的方法,包含我們剛剛使用的 toUpperCase (全部轉大寫) 這個方法

proto

除此之外 String() 本身就是一個函式,只是作為一個建構式 new 來使用,因此它也有自己的 prototype 哦~

如果想要針對 String 增加自己寫的 prototype 也是沒問題的,就如課程範例相同

1
2
3
4
5
6
var myName = new String('ray');

String.prototype.lastText = function () {
return this[this.length - 1];
}
console.log(myName.lastText()); // y

透過這種方式,我們就可以修改各種包裹物件的原型方法,就算是使用純值也是可以的

1
2
3
4
5
6
var myName = 'ray';

String.prototype.lastText = function () {
return this[this.length - 1];
}
console.log(myName.lastText()); // y

每一個純值都有它的包裹物件,舉凡字串、數字等,那麼因為原型都是共用的,因此當我們修改了 String 的原型,所以我們就可以直接套用,這也就是原型的概念。

想當然 JavaScript 還有相當多的建構式可以用,其中包含我們開發常用的 new Date() 也是,其中當我們在使用時間的時候,往往都必須自己重新組裝,若能夠善加利用原型的觀念,那麼就可以這樣子撰寫

1
2
3
4
5
6
7
8
9
10
var date = new Date();
Date.prototype.getFillDate = function () {
var dd = String(this.getDate());
var mm = String(this.getMonth() + 1);
var yyyy = String(this.getFullYear());

return yyyy + '/' + mm + '/' + dd;
}

console.log(date.getFillDate()); // 2021/2/20

這邊比較需要注意的是,我們是將 getFillDate 建立在 prototype 因此是必須使用建構式的,否則你單純輸入以下程式碼是會出現錯誤的

1
2
3
4
5
6
7
8
9
10
11
12
Date.prototype.getFillDate = function () {
// 這邊使用 String 做型別轉換的原因在於
// 主要是避免取出來的時間是數字而導致使用加號運算子時變成相加問題
// ex: return yyyy + mm + + dd;
var dd = String(this.getDate());
var mm = String(this.getMonth() + 1);
var yyyy = String(this.getFullYear());

return yyyy + '/' + mm + '/' + dd;
}

console.log(Date.getFillDate()); // TypeError: Date.getFillDate is not a function

參考文獻