popeye-ux
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
      • Invitee
    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Versions and GitHub Sync Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
Invitee
Publish Note

Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

Your note will be visible on your profile and discoverable by anyone.
Your note is now live.
This note is visible on your profile and discoverable online.
Everyone on the web can find and read all notes of this public team.
See published notes
Unpublish note
Please check the box to agree to the Community Guidelines.
View profile
Engagement control
Commenting
Permission
Disabled Forbidden Owners Signed-in users Everyone
Enable
Permission
  • Forbidden
  • Owners
  • Signed-in users
  • Everyone
Suggest edit
Permission
Disabled Forbidden Owners Signed-in users Everyone
Enable
Permission
  • Forbidden
  • Owners
  • Signed-in users
Emoji Reply
Enable
Import from Dropbox Google Drive Gist Clipboard
   owned this note    owned this note      
Published Linked with GitHub
1
Subscribed
  • Any changes
    Be notified of any changes
  • Mention me
    Be notified of mention me
  • Unsubscribe
Subscribe
# 何謂強制轉型、以及如何作到轉換型別? +++ title = "何謂強制轉型、以及如何作到轉換型別?" description = "如果有人打你的右臉,連左臉也轉過來由他打!" author = "POPEYE" date = "2021-12-20" tags = ["JavaScript", "型別", "強制轉型","型別轉換"] categories = ["JavaScript"] [[images]] src = "img/2021/coercion.jpg" alt = "何謂強制轉型、以及如何作到轉換型別?" +++ ![](https://i.imgur.com/80LCkl5.jpg) 我們都知道JavaScript的基本型別有以下幾種: 1. String :字串,由一連串的字符 (characters) 組成。 2. Number :數值,為 floating point number。 3. Boolean :true 或 false。 4. undefined :表示現在還沒有給值。 5. null :不知道之前有沒有值,但是現在沒有值。 6. Symbol :ES6 出現的新型別。 JavaScript 的型別不在於變數本身,而在於變數被賦予的值。 如果以上那些你都知道,那你該來看看JavaScript變態的部分—「強制轉型」( **coercion** )。 斯斯有兩種,「強制轉型」也有兩種: - 隱含的強制轉型 — **implicit coercion** - 明確的強制傳型(explicit coercion) ## 隱含的強制轉型 — **implicit coercion** 剛剛提到 JavaScript 的型別不在於變數本身,而在於**變數被賦予的值**。 JavaScript 在運算的時候,如果看到兩個不同型別的值,就會自動判斷,把值轉換為相同型別,再做運算。很親切(變態)吧!!?? 不多說,讓我們看一下例子,比較容易進入狀況: ```jsx let a = "1"; //字串 a = a + 2; //'12', a為字串"1",數字2與字串相加,被轉型為字串"2" a = a*2 //24 , 在乘法的時候,字串"12"與2相乘,字串被轉型為數值,得出的結果是數值 12 a = a + true //25, 布林值遇到數值,被轉為數字1,相加後變成25 a = a * null //0 , null遇到數值被轉為0,數值與0相乘變成0 a = a / undefined //NaN, undefined無法再被轉型為數字 ``` 以上這些「我變我變我變變變」的情形就是 JavaScript 變數的「強制轉型」,而且是 JavaScript 親切的、自動的、在背後運作的、**「隱含的強制轉型」( implicit coercion )**。一下變字串,一下有變成數字、一下變成布林值...比孫悟空72變還厲害。 這種「隱含的轉型」( implicit coercion )基本上可以轉成三種型別: - 自動轉換為布林值( ToBoolean ) - 自動轉換為數值( ToNumber ) - 自動轉換為字串( ToString ) ### 四則運算時的強制轉型 JavaScript在做四則運算的時候跟小學課本教的一樣,由左而右「先乘除後加減」。 其中以加法(+)最需要注意! 如果是數值的運算,那沒有轉型的問題。「字串」的相加也沒有轉型的問題。 ```jsx var x = 1 + 2; console.log(x); //3 var y = '歐陽鋒是' + '一隻癩哈蟆'; console.log(y); //歐陽鋒是一隻癩哈蟆 ``` 只有在不同型別的狀況下才有轉型的問題: - 當加號 + 兩側有一個是字串的情形下,會將「非字串」的那一邊「自動轉型」為字串,再將兩個字串連接在一起。如果另一方為 number 、 boolean 、 object 的情況下, number 、 boolean 、 object 會去叫用它們的** .toString 「原型方法」**,把自己變成字串,再去和另一個字串組合。 - 當一邊是數字,一邊是 undefined 的時候, undefined 會被試著轉為數字,變成 NaN ,任何數字與 NaN 相加都是 NaN 。 - 當一邊是數字,加號另一邊是 null 的時候, null 會被轉為數字 0 。 ```jsx //數字與字串相加 77 + '49' //'7749' 77 + '四十九' //'77四十九' //字串與字串相加 '七七' + '四十九' //'七七四十九' 77 + {} //'77[object object]' //當數字要跟undefined相加的時候,udefined會被嘗試轉為數字,也就是NaN,還記得NaN的型別是number嗎? 77 + unfined //NaN '七七' + unfined //'七七undefined' //當數字要與null相加時,null會被轉成數字 0 ; 77 + null //77 '七七' + null //77null ``` 而如果是減乘除法( - * / )的情況,除了數值以外的其他基本型別都會透過 Number() 方法轉為數字。物件則在乘除的時候會透過 Number() 方法,轉為數字,在減法時透過 valueOf() 方法轉為數字。 ```jsx 49 - '36' //13 //字串會被轉為數字,也就是NaN 49 - 'abc' //NaN //布林值的true,會被轉行為數字 1 49 - true //48 //布林值的false,會被轉行為數字 0 49 - false //49 49 - undefined //NaN //null會轉為數字0 49 - null //49 49 - {}    //NaN 49 * '10' //490 49 * '四十九' //NaN 49 * true // 49 49 * false //0 49 * {} //NaN ``` 下面附上變數在四則運算時的「自動轉型」規則: | 四則運算 | 數字 | 基本型別非數字 | 物件 | | ------------- |:-------------| :-----|:-----| | 減法 | 正常運算 | Number()方法轉為數字 |透過valueOf()轉為數字| | 乘法 | 正常運算 | Number()方法轉為數字 |Number()方法轉為數字| | 除法 | 正常運算 | Number()方法轉為數字 |Number()方法轉為數字| | 加法 | 正常運算 | 如果是number、boolean透過toString()方法轉為字串,null或undefined透過String()轉為字串 |toString()轉為字串| ### 比較運算子的強制轉型 比較運算子用來比較兩側的數值,比較之後得到布林值 true 或 false。 一個等號 =,我們知道是「指定、賦值」的意思。 ```jsx var x = 49; ``` 在JavaScript中, `==` 是相等的意思,而 `===` 是全等的意思。 ```jsx var x = 49; //數字 var y = '49'; //字串 console.log(x == y); //true,因為 == 在比較兩側的變數是否相等的時候,會自動幫變數轉型。 true == '1'; //true false == '0'; //true true === '1'; //false false === '0'; //false ``` 使用 `==` 相等的時候,會自動替兩側的變數轉型。 當使用 `===` 全等的時候,不會替變數自動轉型,是比較嚴謹的模式,也是比較推薦使用的方法。 比較特別的是,NaN不等於NaN,不管是 `==` 還是 `===`,都是一樣 NaN 不等於 NaN 。 ==的自動轉型規則: - 當遇到「字串」與「數字」做比較的時候,字串會透過 Number() 嘗試轉為數字,再進行比較。 - 如果比較的一方為布林值,則 true 會轉為 1 , false 會轉為 0 。 - 當`==` 的一側為物件型別,另一側為基本型別,物件型別會透過 valueOf() ,轉為對應的基本型別進行比較。 不等於`!=` 與 `!==` `!=` 與「! ==」兩者都是不等於,但是 `!=` 會替變數做自動轉型,而 `!==` 不會替變數自動轉型,推薦使用 `!==` 。 ### 大於>與小於<的強制轉型 我有看到一個數字比大小的有趣例子,借來筆記一下: ```jsx console.log(1 < 2 < 3); // true console.log(3 < 2 < 1); // true ``` 天哪!怎麼會是這樣的結果! 3 < 2 < 1 的布林值竟然是 true ...天要塌了! 其實是因為 < 是由左向右( left to right )去做比較,下面來解釋一下: ```jsx console.log(1 < 2 < 3); 1<2 //true true < 3 //true轉為數字1,1<3,結果為true。 console.log(3 < 2 < 1); 3 < 2 //false false < 1 // false轉為數字0,0<1,所以結果為true ``` 所以才會得出 console.log( 3 < 2 < 1 );會變成 true 的結果。 ![](https://i.imgur.com/EMhtQsq.png) ### Boolean的強制傳型 邏輯運算子( Logical Operator )有 `AND &&` 、 `OR ||` 、`NOT !` 三種。運算子兩側的值經過 ToBoolean 轉換後會得到一個布林值,再由邏輯運算子比較後傳回其中一個值。 `&&` 以及 `||` 進行判斷時,會對左邊的數值進行檢查,如果原本是布林值,就進行後續判斷。如果不是,則透過 ToBoolean 轉換為 true 或 false 。 - AND && :(條件/運算式 A ) && (條件/運算式 B ),如果兩側的值都為 true ,得到 true 的結果;如果其中一方為 false ,則得到 false 。 如果第一個值轉換為true,則回傳第二個值,否則回傳第一個值。 - OR || :(條件/運算式A) || (條件/運算式B),兩側的值只要有一側為 true ,就得到 true 的結果;如果兩側都為 false ,才得到 false 。 如果第一個值轉換為true,則回傳第一個值,否則回傳第二個值。 - NOT ! : true 的結果透過 ! 轉換會得到 false ,而 false 的結果會變成 true。 那些經過ToBoolean轉換後會得到true的狀況太多,而會得到false的值只有以下五種: - undefined - Null - +0、-0 - NaN - 空字串""或'' 其他的值都會轉為true。 ## 明確的強制傳型(explicit coercion) 也就是透過JavaScript提供的函式來進行變數型別轉換,例如: - 轉換為數值型別: Number() 、 parseInt() 、 parseFloat() - 轉換為字串型別: toString() 、 String() - 轉換為布林型別: Boolean() ### Number()、parseInt()、parseFloat() Number()可以將值「嘗試轉型」為「數值型別」,但要並非每種物件都可以順利轉成 number 型別,如果轉型失敗就會變成 NaN (非數值的數值)! parseInt(str [, radix]) 函式能將輸入的字串轉成整數,第二個參數 radix 代表使用哪種進位制轉換。 它會忽略前後空白,在遇到字元被無法解析時,會忽略那個字元與後面的所有字元,停止解析,並回傳目前為止的結果。 如果第一個字元就無法被解析,會回傳 NaN。 parseFloat(str)能將字串轉換為以十進位表示的浮點數。 來看一下範例: ```jsx Number('123'); //123 Number('華山論劍'); //NaN Number('9陰真經'); //NaN Number(null); //0 Number(true) //1 Number([]); //0 Number([1]); //1 Number([1,2,3]); //NaN Number({}); //NaN parseInt('9陰真經'); //9 parseInt('九陰真經'); //NaN parseInt(101010,2); //42 parseFloat('3.1416') //3.1416 ``` ### .toString()、String() String() 與 .toString() 都可以將值轉換為字串型別,差別在於 .toString() 在收到 null 、 undefined 和數字時會報錯。 ```jsx String(123) //'123' String(null) //'null' String('undefined') //'undefined' String(true) //'true' true.toString() //'true' 123.toString() //Uncaught SyntaxError: Invalid or unexpected token null.toString() //Uncaught TypeError: Cannot read properties of null (reading 'toString') undefined.toString() //Uncaught TypeError: Cannot read properties of undefined (reading 'toString') ``` ### Boolean() Boolean() 可以用來將其他的資料型態轉型成布林值型態。還記得前面提過幾種會變成 false 的值嗎? ```jsx Boolean(100) //true Boolean('100') //true Boolean('') //false Boolean(false) //false Boolean(undefined) //false Boolean(null) //false Boolean('""') //true Boolean('false') //true ``` 本來以為這個題目很好寫.....結果寫得一點都不輕鬆,也找不到方法寫得很有趣。幾乎每個知識點都有再深入研究的餘地,就像《浪人劍客》裡面老人對宮本武藏說的:「技是無限的,卻有鑽研的餘地!」 重點整理一下,如果可以掌握一些概念,之後還可以再仔細琢磨: 強制轉型分為兩種: - 隱含的強制轉型:就是 JavaScript 在運算的過程中,依照它的規則在背地裡把值的型別轉換成其他類的型別。 - 四則運算中加法如果遇到「字串」的轉型最需要留意,其他的減乘除都會試圖轉換成數字來處理。 - 使用「===」相等的時候,會自動替兩側的變數轉型。當使用「===」全等的時候,不會替變數自動轉型,建議使用「===」來進行比較。 - 在布林值的轉型部分,請記得: undefined 、 Null 、 +0 、 -0 、 NaN 、空字串都會轉換成 false。 - 明顯的強制轉型:透過 JavaScript 提供的函式來進行變數型別轉換。 - 轉換為數值型別: Number() 、 parseInt() 、 parseFloat() - 轉換為字串型別: toString() 、 String() - 轉換為布林型別: Boolean() 我是初踏入前端領域的老學徒,如果有寫錯的地方還請大家包涵與指正,謝謝大家! 參考資料 - [你懂 JavaScript 嗎?#8 強制轉型(Coercion)](https://cythilya.github.io/2018/10/15/coercion/) - [JavaScript 全攻略:克服 JS 的奇怪部分](https://medium.com/stuarthsu/javascript-%E5%85%A8%E6%94%BB%E7%95%A5-%E5%85%8B%E6%9C%8D-js-%E7%9A%84%E5%A5%87%E6%80%AA%E9%83%A8%E5%88%86-cf44d08ffc0) - [Javascript型別轉換的技巧](https://www.itread01.com/content/1546084624.html) - [JavaScript資料型別轉換](https://www.uj5u.com/qiye/254374.html) - [https://jimmywei01.github.io/2019/05/28/JS-紀錄2-包裹物件、自動轉型/](https://jimmywei01.github.io/2019/05/28/JS-%E7%B4%80%E9%8C%842-%E5%8C%85%E8%A3%B9%E7%89%A9%E4%BB%B6%E3%80%81%E8%87%AA%E5%8B%95%E8%BD%89%E5%9E%8B/) - [認識 parseInt、parseFloat 與 Number 轉換成數字的三種方法](https://medium.com/unalai/%E8%AA%8D%E8%AD%98-parseint-parsefloat-%E8%88%87-number-%E8%BD%89%E6%8F%9B%E6%88%90%E6%95%B8%E5%AD%97%E7%9A%84%E4%B8%89%E7%A8%AE%E6%96%B9%E6%B3%95-276640aedb4e) - [前端工程研究:關於 JavaScript 中 Number 型別的常見地雷與建議作法](https://blog.miniasp.com/post/2020/02/21/JavaScript-Numbers-Deep-Dive) - [淺談JS中String()與 .toString()的區別](https://codertw.com/%E5%89%8D%E7%AB%AF%E9%96%8B%E7%99%BC/254123/)

Import from clipboard

Paste your markdown or webpage here...

Advanced permission required

Your current role can only read. Ask the system administrator to acquire write and comment permission.

This team is disabled

Sorry, this team is disabled. You can't edit this note.

This note is locked

Sorry, only owner can edit this note.

Reach the limit

Sorry, you've reached the max length this note can be.
Please reduce the content or divide it to more notes, thank you!

Import from Gist

Import from Snippet

or

Export to Snippet

Are you sure?

Do you really want to delete this note?
All users will lose their connection.

Create a note from template

Create a note from template

Oops...
This template has been removed or transferred.
Upgrade
All
  • All
  • Team
No template.

Create a template

Upgrade

Delete template

Do you really want to delete this template?
Turn this template into a regular note and keep its content, versions, and comments.

This page need refresh

You have an incompatible client version.
Refresh to update.
New version available!
See releases notes here
Refresh to enjoy new features.
Your user state has changed.
Refresh to load new user state.

Sign in

Forgot password

or

By clicking below, you agree to our terms of service.

Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
Wallet ( )
Connect another wallet

New to HackMD? Sign up

Help

  • English
  • 中文
  • Français
  • Deutsch
  • 日本語
  • Español
  • Català
  • Ελληνικά
  • Português
  • italiano
  • Türkçe
  • Русский
  • Nederlands
  • hrvatski jezik
  • język polski
  • Українська
  • हिन्दी
  • svenska
  • Esperanto
  • dansk

Documents

Help & Tutorial

How to use Book mode

Slide Example

API Docs

Edit in VSCode

Install browser extension

Contacts

Feedback

Discord

Send us email

Resources

Releases

Pricing

Blog

Policy

Terms

Privacy

Cheatsheet

Syntax Example Reference
# Header Header 基本排版
- Unordered List
  • Unordered List
1. Ordered List
  1. Ordered List
- [ ] Todo List
  • Todo List
> Blockquote
Blockquote
**Bold font** Bold font
*Italics font* Italics font
~~Strikethrough~~ Strikethrough
19^th^ 19th
H~2~O H2O
++Inserted text++ Inserted text
==Marked text== Marked text
[link text](https:// "title") Link
![image alt](https:// "title") Image
`Code` Code 在筆記中貼入程式碼
```javascript
var i = 0;
```
var i = 0;
:smile: :smile: Emoji list
{%youtube youtube_id %} Externals
$L^aT_eX$ LaTeX
:::info
This is a alert area.
:::

This is a alert area.

Versions and GitHub Sync
Get Full History Access

  • Edit version name
  • Delete

revision author avatar     named on  

More Less

Note content is identical to the latest version.
Compare
    Choose a version
    No search result
    Version not found
Sign in to link this note to GitHub
Learn more
This note is not linked with GitHub
 

Feedback

Submission failed, please try again

Thanks for your support.

On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

Please give us some advice and help us improve HackMD.

 

Thanks for your feedback

Remove version name

Do you want to remove this version name and description?

Transfer ownership

Transfer to
    Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

      Link with GitHub

      Please authorize HackMD on GitHub
      • Please sign in to GitHub and install the HackMD app on your GitHub repo.
      • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
      Learn more  Sign in to GitHub

      Push the note to GitHub Push to GitHub Pull a file from GitHub

        Authorize again
       

      Choose which file to push to

      Select repo
      Refresh Authorize more repos
      Select branch
      Select file
      Select branch
      Choose version(s) to push
      • Save a new version and push
      • Choose from existing versions
      Include title and tags
      Available push count

      Pull from GitHub

       
      File from GitHub
      File from HackMD

      GitHub Link Settings

      File linked

      Linked by
      File path
      Last synced branch
      Available push count

      Danger Zone

      Unlink
      You will no longer receive notification when GitHub file changes after unlink.

      Syncing

      Push failed

      Push successfully