iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 9
0
Modern Web

【這些年我似是非懂的 Javascript】系列 第 9

【這些年我似是非懂的 Javascript】Day 9 - 魔幻邪惡的強制轉型 #第二章 #明確的強制轉型

接著昨天那篇
這些年我似是非懂的 Javascript】Day 8 - 魔幻邪惡的強制轉型 #上篇 # 心情轉折

今天來分享明確強制轉型
而這個明確的強制轉型是大家都認同的不邪惡也不魔幻,因為其他語言大部分轉型也是差不多的做法,會叫明確的強制轉型是因為他可以很明顯的看出來他最後的行為。

明確的 String 與 Number 的強制轉型

這個應該是最常見的在 string 與 number 之間互換,
通常是用內建的 String(..) 或是 Number(..),而且我們不用使用 new ,所以我們也不是在建立物件包裹器。
用法如下

const a = 18;
const b = String(a);
b; // "18"

const c = "19";
const d = Number(c);
d; // 19

ToString 的規則和 ToNumber 的規則在上一篇有提過~

除了上面範例的轉換方式還有以下的用法~

const a = 18;
const b = a.toString();
b; // "18"

const c = "19";
const d = +c;
d; // 19

toString() 這個是我個人滿常使用的,書中提到其實他看起來雖然是"明確的",但是他實際上有不容易看出來的隱含性,原因是 toString() 這個不能用在直接是基本型別的值上,因為 JS 會自動把他封裝所以他才能被呼叫,所以這又稱之為"明確地隱含"。

看到這是不是想說...貴圈真亂xD

還沒完呢~
+ 這個運算子的單元運算形式不會有任何運算的動作,但是他會把後面那個 c 強制轉為 number 值 ,而這個算隱含的強制轉型還是明確的強制轉型,書上是說看個人經驗和觀點,但是在 JS 的社群中普遍被接受的是他是"明確的"。

我個人是覺得他是隱含的,因為我沒看過這種用法,而且我不深入去查,我會不知道他是強制轉型成 number。

還是不太建議使用 +c 這種用法,畢竟就算我知道或是你知道,很難保證之後維護的同伴也知道,明確的強制轉型就應該要很明確不應該存在太多的不確定性降低混淆的風險,但書上編排是放在明確的轉型我想是因為社群主要認同(?。

日期轉為數字

剛剛提到的 + 這個單元運算子除了上述用法還有一個功能是將 Date 物件強制轉型成一個 number

我也是第一次知道xD

來看看以下範例

const a = new Date();

+a; // 1600876740123

另外 new Date();() 是 option 的所以你可以能會看到 new Date這種用法,但是看起來並不會提升可讀性(我個人認為),還是會造成混淆之類的副作用xDD。

如何使用非強制轉型也可以拿到時間戳的方法?
可以使用 getTime();

const a = new Date().getTime();

a // 1600876740123

除了上面那種兩個方式之外,還有一個方式是我個人滿常使用的拿時間戳的方法

const a = Date.now();

a // 1600876740123

小總結:

如果你想要拿"現在的"時間戳可以使用 Date.now();
反之你想要拿"非現在的"時間戳你可以使用 new Date(..).getTime();

明確的剖析數值字串

從一個 string 內容剖析(parse) 成數字可以達成像是強制轉型的行為,但是他看起來行為上有些不同,如以下範例。

const a = "17";
const b = "17px";

Number(a); // 17
Number(b); // NaN

parseInt(a); 17
parseInt(b); 17

why?
因為字串剖析可以"容忍"非數值字元,從左到右遇到就停下來,
而反之直接使用強制轉型就換轉換失敗所以最後產生NaN

所以他們兩個本質上要處理的事情其實是不同的,不應該互相替代使用。

例如我都亂用QQ

parseInt(..) 只能使用在 string 值,
其他的都會被自動轉成 string ,譬如說 function, number, object ... 等等

但幾咧!

所以他是隱含的強制轉型...嗎?
對!(難道還不夠明顯嗎xD)

所以這點要非常小心和注意(感覺是個坑)。

上面講的只是第一個坑,
在 ES5 之前還有一個坑是關於 parseInt(..) 當如果你沒有傳入第二個參數來說明你要解讀的值的基值(8 進位、10 進位、16 進位之類的),他就會自動幫你看開頭例如 0x or 0X 就是 16 進位,0 開頭就是 8 進位 ,
聽起來滿自動滿美好的啊!?
根本不是xDD
萬一是小時譬如 08 點,
整個就是
...

但是他真的在 ES5 之前就無解嗎?
有!
就是你要記得傳入第二個參數,如以下範例

const hour = parseInt('08',10);

你以為就只有兩個坑嗎?xDD
還有!

parseInt(1/0, 19) // 18

說好的無限呢!!!?
簡單來說他幹了一件事就是結果會變成這樣

parseInt(Infinity, 19) // 18

剛剛說過... 他會從左到右開始抓!
所以第一個字拿到 "I",第二個字拿到 "n"

I -> 18
n -> 看不懂,不在 19 的基數中

所以得到 18
真的是非常棒xD

總結來說就是不要亂用xDD
parseInt(..) 請使用在 string,避免意想不到的事發生。

明確的從任何非 Boolean 值強制轉型成 Boolean

前面提到 + 會將值強制轉型成 number,而 ! 這個非常常見的否定運算子,問題在於他可以反轉他的值,把 true 變 false ,所以常見的方式是他會明確的強制轉換成 Boolean 就是使用雙否定運算子(!!)
傳說中的...

我相反你的相反

翻過去轉過來的概念xD
直接看範例

const a = "0";
!!a; // true

const b = [];
!!b; // true

const c = {};
!!c; // true

const d = "";
!!d; // false

const e = 0;
!!e; // false

const f = null;
!!f; // false

let g;
!!g; // fasle

強制轉型 Boolean 的另一個用途是在 JSON 序列化的過程強制進行轉型,如下範例。

const a = [
    1,
    function(){/*..*/};
    2,
    function(){/*..*/};
]

JSON.stringify(a); // "[1,null,2,null]"

JSON.stringify(a,function(key,val){
    if(typeof val == "function"){
        return !!val; //強制轉型
    }
    else{
        return val;
    }
}); // "[1,true,2,true]"

三元運算子所隱含的秘密

const a = 17;
const b = a ? true:false;

上面是之前介紹過三元運算子範例,
但是他其實有一個隱含強制轉型的存在,就是...
a 的那個地方他會強制轉型為 boolean 才會開始做真假值的判斷,
書上寫說他可以叫做 "明確的隱含"...
我還是那句...

貴圈真亂xD

盡量避免使用這種用法 (不是指三元運算子,是單指這樣的強制轉型方式)。

以上是今天分享的內容
感謝收看。


分享一個掌控時間的撇步關於昨天提的"黃金讀書和寫文章",

就是...

  1. 打開電腦
  2. 將手機開勿擾丟到你摸不到的位置(最好不要有震動)
  3. 電腦的任何社交頁面和軟體全部關閉,最多只有音樂相關的應用程式
    (不要用 Youtube 聽請善用 Youtube music 或其他只有音樂的軟體)

個人經驗是打開 Youtube 會從找歌變成看影片,
很恐怖!
真的xD


感謝您的收看
我們明天持續分享"魔幻邪惡的強制轉型系列" 第三章-隱含的強制轉型

我們明天見~


參考來源:

你所不知道的 JS|導讀,型別與文法 (You Don't Know JS: Up & Going)


上一篇
【這些年我似是非懂的 Javascript】Day 8 - 魔幻邪惡的強制轉型 #第一章 # 心情轉折
下一篇
【這些年我似是非懂的 Javascript】Day 10 - 魔幻邪惡的強制轉型 #第三章 #隱含的強制轉型
系列文
【這些年我似是非懂的 Javascript】34

尚未有邦友留言

立即登入留言