iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 12
0
Modern Web

教練我想學 JavaScript 系列 第 12

Day 12 存在(exeistence)、布林(Boolean) 與預設值

  • 分享至 

  • xImage
  •  

動態型別和強制型轉真的很有用嗎
讓我們談談存在(exeistence)和布林(boolean)
我打開開發者工具
我使用內建函數
有個布林內建函數可以轉換
雖然不建議用內建函數
但內建函數方便我們得知一個值被強制轉型後的值是什麼

所以,如果我轉換成布林
true 或 false 讓我們來看看:

Boolean(undefined);

Boolean(null);

Boolean("");

當我把 undefined 轉成 Boolean,
undefined 變成 false
null 呢?
null 是 false.
空字串呢?
空字串也是 false.
所以這些東西都表示不存在 所以轉換成 false
如下圖:

可以利用這些特性

所以,如果我轉換成布林 true 或 false 讓我們來看看
當我把 undefined 轉成 Boolean,
undefined 變成 false
那 null 呢?null 是 false.
空字串呢?空字串也是 false.
所以這些東西都表示不存在 所以轉換成 false
可以利用這些特性

來看個例子:

var a;
// goes to internet and looks for a value

if (a) {
  console.log('Something is there');
}

宣告var a,但不設值
假設我有一些程式碼 可以到網路上尋找值
如果找到了設定 a 為那個值
我可以用 if 陳述句
在 if 陳述句括號裡東西
它會試著轉換為布林

記得在執行環境的創造階段
會在記憶體為這個變數建立位置,然後它會做什麼?
它會把它設定為什麼初始值?
對, undefined.
undefined 會轉換成什麼?
False.

所以我們可以用強制型轉來檢查a是否存在 如果最後 a 是 undefined,因為從未設值,
或 a 是 null,程式碼如下:

var a;
// goes to internet and looks for a value

a = null;
if (a) {
  console.log('Something is there');
}

當我照著邏輯這樣做時 我仍然不會得到任何東西:

如果 a 是空字串,程式碼如下:

var a;
// goes to internet and looks for a value

a = "";
if (a) {
  console.log('Something is there');
}

仍然會轉為 false 所以沒有東西會出現:

但當我有像是字串的東西,不是空的,
程式碼如下:

var a;
// goes to internet and looks for a value
a = 'hi';

if (a) {
  console.log('Something is there');
}

到 Console 中看結果:

看到如何運作了嗎
我們可以利用強制型轉的特性
來檢查變數有沒有值
一個不是 undefined, null, 或空字串的值

現在有個危險的地方
0強制轉型後也是 false

所以如果變數最後的值為0
就有問題
因為0不是不存在
這是個有效的值
程式碼如下:

var a;
// goes to internet and looks for a value

a = 0;

if (a) {
  console.log('Something is there');
}

但 a 會被強制轉型為變成布林值
所以我重新整理,不會得到console.log 因為它是 false
0 變成 false.
在 Console 中結果:

所以我可以這樣做 如果我想到這個可能性的話,
我會在 if 條件判斷中添加 || a === 0.
程式碼如下:

var a;
// goes to internet and looks for a value

a = 0;
if (a || a === 0) {
  console.log('Something is there');
}

這樣做的話
運算子優先性和相依性表格
拉下來 || 運算子的優先性比 === 運算子低
所以「完全相等」函數會先執行,在這個「或」函數之前
首先它會執行 === 運算子, 因為使用 === 運算子不會在比較前強制轉換為相同的型別, 因為變數 a 的值為 0 ,透過 === 運算子進行比較後會回傳 true 然後執行 console.log

|| 運算子左邊的變數 a 會被強制轉型,因為變數 a 的值是 0 在 if 判斷內會被轉型為 false
因為 if 判斷 () 內會預期回傳布林值
然後這會變成 if (false || true)
false || true 會回傳 true
在這個函數中,其中一個是 true 或都是 true 的話 就會回傳true
所以這變成true

所以我會看到 Something is there.

所以如果變數 a 的值不是 undefined 不是 null, 不是空字串
你可能不需要這樣做,
因為如果它的值幾乎不太可能會是 0 的話可能只要這樣寫 if(a) 看它存不存在就好了

程式碼如下:

var a;
// goes to internet and looks for a value

if (a) {
  console.log('Something is there');
}

這些技巧在開發中很常使用,因此要把這觀念弄清楚

預設值

回顧一下運算子的強制型轉
從另一個角度看如何利用它們的特性
從一個在很多框架中常用的方法看看

創造一個新的函數叫作 greet.
他需要用name當參數
做的事很簡單 console.log('Hello' + name), 然後呼叫greet
程式碼如下:

function greet(name) {
  console.log("Hello " + name);
}

greet("Jimmy");

我傳入我的名字 Jimmy
好的,在 Console 中執行看看

但如果我呼叫greet但沒有參數呢?
程式碼如下:

function greet(name) {
  console.log(name);
  console.log("Hello " + name);
}

greet();

所以如果我到 Console 中看結果:

不同於很多程式語言 JavaScript 不在乎
這不會丟出錯誤訊息
它會當做 name 沒有東西
結果是我們預期的,對吧?
undefined

因為當函數被呼叫時發生什麼事?
一個新的執行環境被創造 然後這個變數 name 在被執行(呼叫)時被創造
是在函數內被創造,雖然傳入的值是在呼叫時才知道 但這個變數在記憶體已經被設定為 undefined
所以 JavaScript 忽略了
我不用參數呼叫這個函數 然後覺得這很OK

加號運算子將 undefined 強制轉型成字串 'undefined'
所以在 Console 中最終結果為:

因為我們已經知道運算子和強制型轉如何運作
但我們該怎麼辦?
如果我想要一個預設值給這個參數呢?

你會看到有個很棒的方法設定預設值,
程式碼如下:

function greet(name) {
  name = name || "<Your name here>";
  console.log("Hello " + name);
}

greet();

在 Console 中看結果:

所以如果沒有東西
如果 undefined, 是函數被呼叫時最終的值
記得運算子只是會回傳值的函數
所以這個 || 運算子
回傳什麼?
他其實做了很簡單的事情
他不只是回傳 true 或 false

在 Console 中看看 || 運算子的結果:

這回傳 true.

如果我試 undefined or hello, 它不是回傳 true or false
而是回傳 hello

在這情況下,他回傳可以被強制轉型為 true 的值
因為如果我強制轉型 hello ,一個不是空的字串 它是 true

這就是 || 運算子回傳的

如果我放 hi 和 hello 回傳 hi,因為他回傳第一個被轉換成 true 的值

所以這是 || 運算子的特殊行為

如果你傳入兩個可以被轉型成true和false的, 它會回傳第一個被轉型成true的值

1 可以被轉換成 true,
0轉成 false

所以我可以用這個來表示 如果這東西不存在或是空字串或是 null 那就給我預設值(能被運算子強制轉型成 true 的值)

我們在 Console 來看:

看出怎樣運作的嗎?
運算子是會回傳值的函數

回到我們的程式碼:

function greet(name) {
  name = name || "<Your name here>";
  console.log("Hello " + name);
}

greet();

如果 name 是 undefined,或空字串或 null, 那這個 || 函數、這個 || 運算子
會回傳預設值給等號運算子
所以 || 運算子會在 = 運算子之前執行,
因為優先性 指派(等號)運算子的優先性比 || 運算子低,所以 || 運算子先執行
如果這是 undefined 就會回傳預設值
然後等號被執行

在 Console 中的結果為:

如果我同時呼叫 greet 兩次,
程式碼如下:

function greet(name) {
  name = name || "<Your name here>";
  console.log("Hello " + name);
}

greet("Jimmy");
greet();

當 Jimmy 被傳入,這會是true 因為這不是空字串或 undefined, 所以 Jimmy 這個字串會強制轉型為true
這就是 || 運算子會回傳的
所以 name 會被設為 Tony

我們到 Console 中看結果:

我可以用if陳述句來設定,但會比較多行程式
這很簡潔
當你瞭解之後,可以很清楚讓你閱讀程式碼

你仍然需要注意 0
如果呼叫 greet 時我將 0 當作參數傳入,
程式碼如下:

function greet(name) {
  name = name || "<Your name here>";
  console.log("Hello " + name);
}

greet(0);

0 會被轉換成false

所以我會得到預設值

所以你需要注意 0
然而,這是特例
在大多時候設預設值是很好的
在 JavaScript 中可以做的很簡潔


上一篇
Day 11 比較運算子
下一篇
Day 13 物件與點
系列文
教練我想學 JavaScript 30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言