[譯]隱式轉型,你值得掌握

前幾天突然發現github上有一個大熱門項目 —— 「33 concepts every JavaScript developer should know」,目前已經將近25000個Stars。這個項目旨在幫助前端開發者掌握33個JavaScript基礎概念。按做者話說,這些概念並非開發所必需的,但它們是引導你通向前端大牛之路的基石。javascript

遺憾的是,該項目中文版的文章收錄不盡完整。因此本着學習與交流的目的,本人會把33個概念所涉及的文章利用業餘時間竭盡所能的翻譯出來,其中難免疏漏,望請指正。本文是第四篇,如下爲正文:前端


隱式轉型是指,JavaScript會把一個非預期值轉換爲預期值。java

什麼意思呢?git

在必定條件下,你可以把一個字符串看成數值使用,也可以把一個對象看成字符串使用,這些類型可以發生轉換,以知足你的預期。然而,咱們應儘可能避免JavaScript的這一語言特性。github

3 * "3" //9
1 + "2" + 1 //121

true + true //2
10 - true //9


const foo = {
  valueOf: () => 2
}
3 + foo // 5
4 * foo // 8

const bar = {
  toString: () => " promise is a boy :)"
}
1 + bar // "1 promise is a boy :)"


4 * [] // 0
4 * [2] // 8
4 + [2] // "42"
4 + [1, 2] // "41,2"
4 * [1, 2] // NaN

"string" ? 4 : 1 // 4
undefined ? 4 : 1 // 1
複製代碼

數字表達式中的非數值

字符串數組

當一個字符串參與到數學運算中來時,如涉及如下四種運算:-*/%,則至關於爲該字符串調用了內置的Number()函數。這很容易理解,任何包含數字的字符串都會轉換爲數字,對於含有非數字字符的,則返回NaN,具體參考Number()轉換規則。示例以下:promise

3 * "3" // 3 * 3
3 * Number("3") // 3 * 3
Number("5") // 5

Number("1.") // 1
Number("1.34") // 1.34
Number("0") // 0
Number("012") // 12

Number("1,") // NaN
Number("1+1") // NaN
Number("1a") // NaN
Number("one") // NaN
Number("text") // NaN
複製代碼

+」操做符是個例外函數

不像其它數學運算符,「+」表現出兩種特性:學習

  1. 加法
  2. 字符串拼接

字符串參與「+」操做時,JavaScript再也不把字符串轉爲數字,反會將數字轉爲字符串。ui

// 字符串拼接
1 + "2" // "12"
1 + "js" // "1js"

// 加法運算
1 + 2 // 3
1 + 2 + 1 // 4

// 先加法,再拼接
1 + 2 + "1" // "31"
(1 + 2) + "1" // "31"

// 所有拼接
1 + "2" + 1 // "121"
(1 + "2") + 1 // "121"
複製代碼

對象

JavaScript中大多數對象都會轉換爲「[object Object]」,好比:

"name" + {} // "name[object Object]
複製代碼

每一個JavaScript都會繼承toString()方法,這就說明不管什麼時候,對象度可以被轉換爲字符串。接下來,toString()方法的返回值就會參與到字符串拼接和數學運算中去。

const foo = {}
foo.toString() // [object Object]

const baz = {
  toString: () => "I'm object baz"
}

baz + "!" // "I'm object baz!"
複製代碼

對象參與數學運算時,JavaScript會試圖將它的返回值轉換爲數字;字符串拼接時,則轉換爲字符串。

const foo = {
  toString: () => 4
}

2 * foo // 8
2 / foo // 0.5
2 + foo // 6
"four" + foo // "four4"

const baz = {
  toString: () => "four"
}

2 * baz // NaN
2 + baz // 2four

const bar = {
  toString: () => "2"
}

2 + bar // "22"
2 * bar // 4
複製代碼

數組

數組一樣繼承了toString()方法,然而在工做方式上則略有不一樣,轉換的過程至關於爲數組調用了一個沒傳參的join()方法。

[1,2,3].toString() // "1,2,3"
[1,2,3].join() // "1,2,3"
[].toString() // ""
[].join() // ""

"me" + [1,2,3] // "me1,2,3"
4 + [1,2,3] // "41,2,3"
4 * [1,2,3] // NaN
複製代碼

當你把數組看成字符串使用時,JavaScript會將toString()的返回值和另外一個值拼接起來;看成數字使用時,返回值則轉換爲數字。

4 * [] // 0
4 / [2] // 2

// 至關於
4 * Number([].toString())
4 * Number("")
4 * 0

//

4 / Number([2].toString())
4 / Number("2")
4 / 2
複製代碼

True, False 和 ""

Number(true) // 1
Number(false) // 0
Number("") // 0

4 + true // 5
3 * false // 0
3 * "" // 0
3 + "" // "3"
複製代碼

The valueOf() method```

在JavaScript中,你一樣能夠定義一個valueOf()方法,它也能夠將對象轉換爲字符串或數值。

const foo = {
  valueOf: () => 3
}

3 + foo // 6
3 * foo // 9
複製代碼

toString()valueOf()方法同時在對象中出現時,JavaScript會優先調用valueOf方法。

const bar = {
  toString: () => 2,
  valueOf: () => 5
}

"sa" + bar // "sa5"
3 * bar // 15
2 + bar // 7
複製代碼

真和假

JavaScript中的每一個值均可以轉換爲truefalse。轉換爲true意味着該值爲真,反之則爲假。

其中有爲數很少的值會被轉換爲false,它們是:

  1. false
  2. 0
  3. null
  4. undefined
  5. NaN
  6. -0

除此之外,全部值都爲真。

if (-1) // truthy
if ("0") // truthy
if ({}) // truthy
複製代碼

上面的代碼正如咱們所預期,可是在實踐中咱們仍應該顯式的肯定一個值是否爲真。整體上,咱們應當避免使用隱式轉型,即使你認爲已將它爛熟於胸了。

下面的代碼纔是你應該參考使用的:

if (counter === 2)

//or

if (typeof counter === "number")
複製代碼

假如,你定義了一個處理數字的函數。

const add = (number) => {
  if (!number) new Error("Only accepts arguments of type: number")
  //your code
}
複製代碼

當你調用這個函數,並想傳入參數 0 時,函數會給你拋出一個錯誤。

add(0) // Error: Only accepts arguments of type: number

// 更好的嘗試

const add = (number) => {
  if (typeof number !== "number") new Error("只接受數字類型: number")
  //your code
}

add(0) // 這下沒錯了
複製代碼

NaN

NaN 是一個特殊的數值,它與任何值都不相等,包括 NaN 自己

NaN === NaN // false

const notANumber = 3 * "a" // NaN

notANumber == notANumber // false
notANumber === notANumber // false
複製代碼

NaN 是JavaScript中惟一一個本身不等於本身的值,你能夠利用這個特性來檢查NaN

if (notANumber !== notANumber) // true
複製代碼

ES6標準引進了一種用來檢查 NaN 的新方法 Number.isNaN

Number.isNaN(NaN) // true
Number.isNaN("name") // false
複製代碼

使用這個函數時須要注意,它會首先將參數轉型,而後纔開始檢查 NaN,示例以下:

const coerceThenCheckNaN = (val) => {
  const coercedVal = Number(val)
  return coercedVal !== coercedVal ? true : false
}

coerceThenCheckNaN("1a") // true
coerceThenCheckNaN("1") // false
coerceThenCheckNaN("as") // true
coerceThenCheckNaN(NaN) // true
coerceThenCheckNaN(10) // false
複製代碼

(完)

下一篇講述相等操做符和全等操做符,敬請期待

相關文章
相關標籤/搜索