方格精選

【前端基礎】關於 JavaScript 的型別系統:自動轉型、真值與假值

更新於 2024/01/25閱讀時間約 6 分鐘

在先前的型別文章中,我們曾經聊過 JavaScript 常用的一些型別,但針對布林這個型別,我們沒有做太多的解釋,原因在於布林值在 JavaScript 會有一個特殊的規則:自動轉型 。

自動轉型可說是讓 JavaScript 為弱型別、且難以管理的最重要的要素,接著就來讓我們來聊聊什麼是自動轉型吧。

自動轉型是什麼?

在 JavaScript 中,並沒有限定型別一定要一樣才能進行運算,這是什麼意思呢?舉例來說:我們可以拿字串與數字進行累加:

1 + '1'
// ?

也可以拿不同型別的值來進行比較:

1 > '1'
// ?

1 === '1'
// ?

0 == false
// ?

顯然其中有詐,要不是 JavaScript 有做一些什麼事,不然怎麼會讓不同型別間進行比較呢?這是因為,JavaScript 會依照當下運算情境,來決定是不是要替其中的值自動做轉型,這個過程就是我們所常聽到的自動轉型了,接著我們來看一些常見的轉型規則與情境吧!

自動轉型的時機規則

以下是一些 JavaScript 常見的轉型規則:

字串與數字進行邏輯運算:

JavaScript 真的是一個很神奇的語言,字串型別與數字型別可以相加到底是指什麼?舉例來說:把字串 ‘ Vivian’ 加上數字 1 結果會是什麼?

以常理來說我們沒有辦法拿非數字的東西與數字來進行大小的比較,或是進行加減乘除,於是聰明的 JavaScript 在遇到字串與數字邏輯運算時,會把字串或是數字去做一些轉型,很酷吧?

讓我們來看一些常見的數字轉字串的自動轉型:

  • 數字與字串累加:早期來沒有樣板字面值時,常常會需要多種欄位來源的字串組成一串句子,在 JavaScript 中,累加不一定是針對數字進行累加,加號運算子還可以用來進行字串的組合,如果加號運算子,左右兩側有字串及數字的話,就會將數字轉為字串型別:
1 + '1'
// '11'
  • 數字與字串相減、乘、除:當遇到減法運算子時,若是有字串型別,JavaScript 就會嘗試使用 Number() 的方法將字串轉為數字看看,但也有可能字串無法轉型而導致出錯,出現 NaN (非數字)的型別出現:
2 - '1'
// 1

'vvn' - 1
//NaN

'vvn' * 8
// NaN,不會出現 8 個 vvn 喔

'vvn' / 2
// NaN

布林值轉型:真值與假值

在先前的文章中,我們曾經提到布林是 JavaScript 奇怪機制的其中一員,除了自動轉型的機制外,我們還會討論一個延伸議題:真值與假值。

JavaScript 型別基本上都可以被轉成布林值,能被轉為 true 稱為真值(Truthy Value),被轉為 false 的為假值(Falsy Value),因為真值的情境舉不完,我們直接來看哪一些型別可以被轉為假值,我們可以用 Boolean 這個方法來檢核:

Boolean(0);
// false

Boolean('');
// false

Boolean(undefined);
// false

Boolean(null);
// false

Boolean(NaN);
// false

Boolean(false);
// false,別忘記 false 本身也是一種假值

以上就是 6 種 JavaScript 假值的狀況,很多初級的前端工程師面試算是必考的題目,一開始大家可能都會想要用背的,不過對有一些開發經驗的人來說,可能會發現一些端倪。

假值的情境基本上是「容易出錯」、「空值、未定義」的情境,舉例來說:當資料要呈現在畫面上時,我們不會希望當沒有資料時,出現「空殼」似的 UI ,或是在一些資料型別錯誤時,這些資料還是會如實出現在頁面上,這都是需要被避免掉的。

通常在條件判斷時,例如:使用三元運算子、 if else 判斷式時, JavaScript 會需要將比對邏輯轉為布林值,所以我們就必須理解 JavaScript 自動轉型的規則,才能在這些時機點寫出嚴謹的判斷,而不是因為自動轉型的規則導致流程判斷結果異常。

為了優化流程判斷,實務開發時有許多工程師會將判斷假值寫成一個共用函式:

const isEmpty= (value) => value === ''|| value === undefined|| value === null;  

在需要的時候引入函式,就可以減少誤用假值的狀況出現,這邊還要注意一個狀況,實務上的空陣列與空物件並不是假值,至於如何檢核空陣列與空物件的情境,之後有機會再跟大家聊聊。

JavaScript 中的型別都可以轉成布林,而布林值在有些情境下也會進行自動轉型,以下內容比較跟實務開發無關,比較是 JavaScript 這門語言的特性,面試也許會考到。

// 布林值遇到數字運算時,會跟字串一樣先用 Number() 來進行轉型
// true -> 1, false -> 0

true > 0
// -> true

false < 1
// -> true

下方的情境又更加神奇了一點:

// 遇到累加時,要看運算對象中有沒有字串決定轉型規則
// 若布林值的運算對象為數字,則先使用 Number() 轉型布林值
// 若布林值的運算對象為字串,則先使用 toString() 轉型為字串
// 註:要搭配 JavaScript 中的優先序一起看

true + 1
// -> 2

true + 1 + '1'
// -> '21'

true + (1 + '1')
// -> 'true11'

2 + false + 1
// -> 3

如何避免自動轉型?

要避免自動轉型的話有幾種方式:

  1. 使用靜態碼分析工具 TypeScript ,詳細介紹可以參考這篇文章
  2. 搞懂 JavaScript 的轉型規則。
  3. 把假值的判斷額外封裝成函式調用。
  4. 在做流程判斷的時候把空值的情境考量進去,並進行額外的判斷。
  5. 寫預設值

自己覺得流程判斷的控制很看開發者自己的習慣,上述方法都是平常我會用來避免 JavaScript 自動轉型出現錯誤的方式,與大家分享。

這篇文章不是很教科書式的分享「自動轉型」或是「真值、假值」這個面試題,而是參雜了一些自己實務上的開發經驗,讓大家理解這個議題不僅僅是面試題而已,還是一個前端工程師非常重要的基礎,在工作上也會持續的遇到,並且要透過理解這在機制找更好的方式處理預期外錯誤。

希望這篇文章會對「自動轉型」、「真值、假值」有疑慮的人有幫助,我是 Vivian ,我們下次見。

為了追求可以窩在座位上、可以心無旁騖思考問題、座位可以亂七八糟沒關係、不需要到處哈腰點頭跑客戶,不用腳踩十公分、連妝都可以不用化的職場人生,文組少女毅然決然踏上RD的養成日常。
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
在剛開始寫 JavaScript 可能大多數的人不會特別意識到 JavaScript 的型別系統有什麼特別之處,我是在看完 Youtube 上 CS50 的課程,才理解到在不同的程式語言中,會因為語言的特性而有不同的系統,JavaScript 就是偏向比較特別的那一種。
在前端開發中,很常會有需要轉址的需求,且處理的手法滿因人而異的,所以今天就想要來整理一些常見的 JavaScript 頁面轉址方式,以及各自的差異。
Functional Programming 中文譯作函式程式設計,或是功能性程式設計,常簡稱為:FP,是一種透過使用純函式(Pure Funciton)進行軟體開發,且避免副作用的程式設計典範,比起宣告式的流程控制,在 FP 採用主要以表達式的方式撰寫程式碼。
Hoisting 可以說是 ES6 問世之後,去面試還是會爾偶被問到的面試考題,雖然 Hoisting 離 Modern JavaScript 的技術有點距離,實作上幾乎不太會用到,但透過了解 Hoisting 的概念,可以對這門語言有更深的了解與掌握度。
對於剛接觸前端開發不久的人來說,可能會對var、let 與 const 的差異略懂略懂,但又說不太出三者實際哪裡不一樣。
在一開始學習前端開發的時候,一直遇到講師在課程內容中提到 ES5、ES6 等關鍵字,當初的我,單純認為 ES5、ES6 是講述 JavaScript 的版本,所以在使用上就沒有想太多,反正就是 JavaScript 1.0 、2.0 的感覺吧?
在剛開始寫 JavaScript 可能大多數的人不會特別意識到 JavaScript 的型別系統有什麼特別之處,我是在看完 Youtube 上 CS50 的課程,才理解到在不同的程式語言中,會因為語言的特性而有不同的系統,JavaScript 就是偏向比較特別的那一種。
在前端開發中,很常會有需要轉址的需求,且處理的手法滿因人而異的,所以今天就想要來整理一些常見的 JavaScript 頁面轉址方式,以及各自的差異。
Functional Programming 中文譯作函式程式設計,或是功能性程式設計,常簡稱為:FP,是一種透過使用純函式(Pure Funciton)進行軟體開發,且避免副作用的程式設計典範,比起宣告式的流程控制,在 FP 採用主要以表達式的方式撰寫程式碼。
Hoisting 可以說是 ES6 問世之後,去面試還是會爾偶被問到的面試考題,雖然 Hoisting 離 Modern JavaScript 的技術有點距離,實作上幾乎不太會用到,但透過了解 Hoisting 的概念,可以對這門語言有更深的了解與掌握度。
對於剛接觸前端開發不久的人來說,可能會對var、let 與 const 的差異略懂略懂,但又說不太出三者實際哪裡不一樣。
在一開始學習前端開發的時候,一直遇到講師在課程內容中提到 ES5、ES6 等關鍵字,當初的我,單純認為 ES5、ES6 是講述 JavaScript 的版本,所以在使用上就沒有想太多,反正就是 JavaScript 1.0 、2.0 的感覺吧?
你可能也想看
Google News 追蹤
Thumbnail
*合作聲明與警語: 本文係由國泰世華銀行邀稿。 證券服務係由國泰世華銀行辦理共同行銷證券經紀開戶業務,定期定額(股)服務由國泰綜合證券提供。   剛出社會的時候,很常在各種 Podcast 或 YouTube 甚至是在朋友間聊天,都會聽到各種市場動態、理財話題,像是:聯準會降息或是近期哪些科
Thumbnail
這篇文章更偏向純紀錄性質,方便日後有需要時直接複製相同指令來完成 Bootstrap 與 Sass 的引入,也會做成一個專案起手式的模板放在 Github ,未來在建置新專案時可以透過直接複製專案,來省去前面重複的這過程。
Thumbnail
微前端是一種現代前端架構,旨在將大型前端應用拆分為獨立、可獨立部署的小模組。這與微服務在後端的策略相似。 本文將探討微前端的基本概念,以及如何在基於Gin的後端系統中實施它,從而實現真正的全棧模組化。
Thumbnail
let 和 const 是 JavaScript 在 ES6 版本中新的變數宣告方式。使用 let 宣告的變數可以重新賦值,而使用 const 宣告的變數賦值後則不能改變。這兩種新的宣告方式提供了比 var 更嚴格和清晰的變數作用域管理。
Thumbnail
JavaScript 陣列的操作方法,forEach() 是用於遍歷陣列的每個元素,並對每個元素執行提供的函數,map() 是創建一個新陣列,其結果是對原陣列中的每個元素調用提供的函數後返回的結果。
Thumbnail
本文將介紹陣列的基本操作方法,包括建立陣列、存取元素、陣列遍歷和修改陣列等,接下來將逐一介紹這些操作,並附上程式碼範例,讓你更易於理解和運用。。
Thumbnail
JavaScript 陣列的操作方法,push() 可以將值加入到陣列的最後一個位置 ,pop() 會移除(取出)陣列的最後一個元素,shift() 會移除陣列的第一個元素,unshift() 則會將指定的元素添加到第一個位置。
Thumbnail
JavaScript 的命名規則相當重要,它有些特定的慣例和限制。例如,變數和函式通常使用小駝峰式(firstName)命名。然後 JavaScript 對大小寫敏感,所以lastName和lastname是不同的變數。
Thumbnail
npm 是一個套件管理工具,開發中經常需要使用第三方套件,npm 是可以用來管理很多套件的工具,這邊指的套件可能是 Library, 框架, 工具等,例如 Bootstrap, jQuery, Vue.js, babel 都可以統一由它管理。
Thumbnail
本文題目來自網站codesignal,它是個可依自己選取的程式語言進行測驗,測驗難易程度會逐題增加,可透過解題來獲得分數以及徽章,相當有趣味性。在sumbit後可在左欄看到票選最高的解法,這些解法來自不同語言,當然你可以在上面篩選自己撰寫的程式語言。沒有所謂的最好的解法,只有最適合的方式。
Thumbnail
*合作聲明與警語: 本文係由國泰世華銀行邀稿。 證券服務係由國泰世華銀行辦理共同行銷證券經紀開戶業務,定期定額(股)服務由國泰綜合證券提供。   剛出社會的時候,很常在各種 Podcast 或 YouTube 甚至是在朋友間聊天,都會聽到各種市場動態、理財話題,像是:聯準會降息或是近期哪些科
Thumbnail
這篇文章更偏向純紀錄性質,方便日後有需要時直接複製相同指令來完成 Bootstrap 與 Sass 的引入,也會做成一個專案起手式的模板放在 Github ,未來在建置新專案時可以透過直接複製專案,來省去前面重複的這過程。
Thumbnail
微前端是一種現代前端架構,旨在將大型前端應用拆分為獨立、可獨立部署的小模組。這與微服務在後端的策略相似。 本文將探討微前端的基本概念,以及如何在基於Gin的後端系統中實施它,從而實現真正的全棧模組化。
Thumbnail
let 和 const 是 JavaScript 在 ES6 版本中新的變數宣告方式。使用 let 宣告的變數可以重新賦值,而使用 const 宣告的變數賦值後則不能改變。這兩種新的宣告方式提供了比 var 更嚴格和清晰的變數作用域管理。
Thumbnail
JavaScript 陣列的操作方法,forEach() 是用於遍歷陣列的每個元素,並對每個元素執行提供的函數,map() 是創建一個新陣列,其結果是對原陣列中的每個元素調用提供的函數後返回的結果。
Thumbnail
本文將介紹陣列的基本操作方法,包括建立陣列、存取元素、陣列遍歷和修改陣列等,接下來將逐一介紹這些操作,並附上程式碼範例,讓你更易於理解和運用。。
Thumbnail
JavaScript 陣列的操作方法,push() 可以將值加入到陣列的最後一個位置 ,pop() 會移除(取出)陣列的最後一個元素,shift() 會移除陣列的第一個元素,unshift() 則會將指定的元素添加到第一個位置。
Thumbnail
JavaScript 的命名規則相當重要,它有些特定的慣例和限制。例如,變數和函式通常使用小駝峰式(firstName)命名。然後 JavaScript 對大小寫敏感,所以lastName和lastname是不同的變數。
Thumbnail
npm 是一個套件管理工具,開發中經常需要使用第三方套件,npm 是可以用來管理很多套件的工具,這邊指的套件可能是 Library, 框架, 工具等,例如 Bootstrap, jQuery, Vue.js, babel 都可以統一由它管理。
Thumbnail
本文題目來自網站codesignal,它是個可依自己選取的程式語言進行測驗,測驗難易程度會逐題增加,可透過解題來獲得分數以及徽章,相當有趣味性。在sumbit後可在左欄看到票選最高的解法,這些解法來自不同語言,當然你可以在上面篩選自己撰寫的程式語言。沒有所謂的最好的解法,只有最適合的方式。