iT邦幫忙

2022 iThome 鐵人賽

DAY 29
0

大綱

  • 轉換為 Boolean
  • 邏輯運算子
  • 相等性運算子、順序運算子
  • Boolean 函式
  • 總結
  • 店小二,上菜 ~ 來個 code !
  • 參考資料

轉換為 Boolean

轉換表

手動轉換為 Boolean

這裡有三種方式可以把任何的值轉為一個 boolean:

  • Boolean(value):推薦使用。
  • value ? true : false:運用三元運算來判斷。
  • !!valu:一個驚嘆號「not」會將值轉換為否定的 boolean:連用兩次來進行非否定的轉換。

書中的想法跟我一樣,會比較偏好使用 Boolean() 來做轉換,因為很直覺,可以很清楚的表達想要做的事。

Example:

Boolean(undefined)       // false
Boolean(null)            // false

undefined ? true : false // false
null ? true : false      // false

!!undefined              // false
!!null                   // false

Example:

Boolean(0)       // false
Boolean(1)       // trur
Boolean(2)       // true

0 ? true : false // false
1 ? true : false // true

!!0              // false
!!1              // true

Example:


Boolean("")           // false
Boolean(" ")          // true
Boolean("hello")      // true
Boolean("true")       // true
Boolean("false")      // true

"" ? true : false     // false
"null" ? true : false // true
"true" ? true : false // true

!!""                  // false
!!"null"              // true
!!"false"             // true

Truthy 與 Falsy 值

在使用 boolean 轉換的方法時,我們預期都會得到一個值,同時我們也可以提供任何值做轉換,結果會得到 true or false 值。

這裡提到要嘛是 true or false 的值,這兩個值被稱為 falsy 值 (假值的值) 與 truthy 值 (真值的值),根據上面整理出來的表格,可以得知以下都是 falsy 值。

  • undefinednull
  • Boolean:false
  • 數字:0NaN
  • 字串:"" (要注意 """ " 的不同)

其他所有的值,包含所有的物件、空物件、空陣列與 new Boolean(false),都是 truthy 值。另外,發現到由於 undefinednull 都是 falsy 值,因此可以使用 if 陳述句 (statement) 來判斷一個變數 x 是否有值。

Example:

if (x) {
	// if x have value, then to do something
}

要注意的是,上面的程式碼意思是會把所有的 falsy 值都解讀為「沒有值」,並不限定於 undefinednull ,因此,更可以撰寫這樣的程式碼來簡化我們的程式。

這裡看狀況要不要再補充。

所有的物件都是 truthy 的

所有的物件都是 truthy 的:

Boolean(new Boolean(false)) // true
Boolean({})                 // true
Boolean([])                 // true

邏輯運算子

這節要介紹 And (&&)、Or (||)、Not (!) 這些邏輯運算子 (logical operators)。

二元邏輯運算子:And (&&)、Or (||)

二元邏輯運算子會:

  • 保留值 (value-preserving):會原封不動地回傳它們運算元的其中一個。

Example:

"abe" || 123     // "abc"

false || "hello" // "hello"範例
  • 短路 (short-circuiting):如果第一個運算元能決定運算結果,哪麼第二個運算元就不會去執行。

看看維基百科的解釋:

短路求值是一種邏輯運算子的求值策略。只有當第一個運算數的值無法確定邏輯運算的結果時,才對第二個運算數進行求值。

Example:

true || "Hello World"  // true,程式只執行到第一個運算元

false || "Hello World" // "Hello World",程式會繼續執行到第二個運算元

邏輯 And (&&)

如果如果第一個運算元轉為 false,就將它回傳。否則,就回傳第二個運算元。

Example:

true && "123"          // "123"

false && "456"         // false

0 && "789"             // 0

"" && "GG"             // ""

"Orz" && "Ni Hao Ma ?" // "Ni Hao Ma ?"

邏輯 Or (||)

如果第一個運算元轉為 true,就將它回傳。否則,則回傳第二個運算元。

EXample:

true || false  // true

123 || "hello" // 123

"" || "def"    // "def"

模式:提供預設值

||設定預設值

利用||的特性,我們可以在宣告變數時,賦予變數預設值,而不需要用if else判斷式。例如以下的例子,假設我不能確定value是否存在,我可以這樣寫:

Example:

const value = theValue || defaultValue // 意思是如果 theValue 就回傳 theValue,不然就回傳 defaultValue

要特別注意的是,如果 theValue 的值是0""falsenullundefinedNaN都會是false(falsy),哪就會得到 defaultValue 的值,另外,書中提供了三種常見的範例做說明。

範例一:參數的預設值

函式 saveText() 的參數 text 是可選擇要不要傳,如果不傳值的話,其值會得到空字串:

Example:

function saveText(text) {
	text = text || ""
}

範例二:特性的預設值

物件 options 可能有可能沒有 title 這個 key,如果沒有的話,設定標題為 "Untitled" 這個值:

Example:

setTitle(options.title || "Untitled")

範例三:函式結果的預設值

函式countOccurrences會計算 regex 的匹配次數:

function countOccurrences(regex, str) {
	// ... 省略,檢查 /g 是否有為 "regex" 而設定
	return (str.match(egex) || []).length
}

上述函式目的是要回傳使用match匹配的次數,有可能都沒有匹配到的話,會得到一個null值,在這裡另外加了一個空陣列來防止錯誤產生,這樣一來在這個情境下都可以很安全的存取 length 這個特性。

邏輯 Not (!)

邏輯運算子 (Not),會將它的運算元轉為 boolean 值,再反向之。

Example:

!true // false

!43   // false

!{}   // false

![]   // false

!""   // true

相等性運算子、順序運算子

  • 相等性運算子:===!====!=
  • 順序運算子:>>=<<=

Boolean 函式

Boolean 這個函式可經由兩個方式使用:

Boolean(value)

做為一個一般函式,它會將 value 轉為一個 boolean 基本型態的值。

Example:

Boolean(0)        // false

typeof Boolean(0) // 'boolean'

new Boolean(bool)

new Boolean(bool) 是一個建構器,它會建立一個 boolean 的新物件。

Example:

typeof new Boolean('Hello world') // 'object'

總結

  • 從這個章節得知,有三種方法可以把任何的值轉為 boolean 值。
    • 知道使用Boolean()來轉換,是最推薦的。
  • 了解拿哪些基本型態的值,轉換 boolean 值,是會得到false值。
  • 了解轉換object值,是永遠會得到true值。
  • 了解 Truthy 與 Falsy 值的概念。
    • 就可以寫出if (!x) {}較為簡潔的程式。
  • 實際應用在函式的場景。

案例分享

Real Example 1:

/**
 * 找 TD 結尾
 * @param {string} service_type
 * @returns {boolean}
 */
export const serviceTypeRule = (service_type) => {
  if (!service_type) return (false)
  const serviceTypeReg = /TD$/g
  const serviceTypeData = service_type.toUpperCase()
  return serviceTypeReg.test(serviceTypeData)
}

serviceTypeRule('ATD')

/**
 * 找 D 開頭
 * @param {string} incoterm
 * @returns {boolean}
 */
export const incotermRule = (incoterm) => {
  if (!incoterm) return (false)
  const incotermReg = /^D/g
  const incotermData = incoterm.toUpperCase()
  return incotermReg.test(incotermData)
}

incotermRule('DAF')

Real Example 2:

const data = records.shipment_list || []
const shipmentCounts = records.group_by_count || { ALL: 0, IN_PROGRESS: 0, COMPLETED: 0, CANCELLED: 0 }

Real Example 3:

import { useState, useEffect, useCallback, useRef } from 'react'

import useOverlayWrap from '../../../commons/hooks/useOverlayWrap'

import { initialValues } from '../configs/SingleNotificationModal/initialValues'
import { fetchSignalShipmentNotification } from '../duck'

const useFetchSignalShipmentNotification = (id, notificationId) => {
  const [hawb, setHawb] = useState(initialValues)
  const fetching = useRef(false)
  const fetched = useRef(false)

  const fetchData = useCallback(async () => {
    fetching.current = true
    try {
      const data = await fetchSignalShipmentNotification(id, notificationId)
      setHawb({
        ata: !!(data && data.ata),
        atd: !!(data && data.atd),
        complete_date: !!(data && data.complete_date),
        out_for_delivery_date: !!(data && data.out_for_delivery_date),
        email_list: data && data.email_list ? data.email_list : undefined,
      })
			
			// 下列程式 ESLint 會自動修正如上述程式
			setHawb({
        ata: data && data.ata ? true : false,
        atd: data && data.atd ? true : false,
        complete_date: data && data.complete_date ? true : false,
        out_for_delivery_date: data && data.out_for_delivery_date ? true : false,
        email_list: data && data.email_list ? data.email_list : undefined,
      })
    } catch (e) {
      console.log(e)
    }

    fetching.current = false
    fetched.current = true
  }, [id, notificationId])

  const overlayWrapCallback = useOverlayWrap(fetchData)

  useEffect(() => {
    if (!fetching.current && !fetched.current) { overlayWrapCallback() }
  }, [overlayWrapCallback])

  return [hawb]
}

export default useFetchSignalShipmentNotification

Real Example 4:

export const AddComma = ({ cell }) => {
  if (!cell) return (null)
  return (
    <div className='number-block'>
      {cell.filter(v => v).join(', ')}
    </div>
  )
}

覺得很經典的範例:

let a1 = new Boolean(false)
if (a1) {
  console.log('Hello')
}

let a2 = Boolean(false)
if (a2) {
  console.log('World')
}
// 這題答案會印出什麼 !?

參考資料

浅谈 var bool= false 和 var bool= new Boolean(false)的区别:

浅谈 var bool= false 和 var bool= new Boolean(false)的区别

JavaScript基本功修練:Day9 - 短路求值與條件運算子的應用:

JavaScript基本功修練:Day9 - 短路求值與條件運算子的應用 - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天

浅谈 var bool= false 和 var bool= new Boolean(false)的区别:

浅谈 var bool= false 和 var bool= new Boolean(false)的区别


上一篇
Day 28 | Function
下一篇
Day 30 | 例外處理與錯誤
系列文
一步一腳印,我的前端工程師修煉30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言