- 原文地址:2ality.com/2013/04/qui…
- 原文做者:Dr. Axel Rauschmayer
- Markdown 地址:github.com/Yangfan2016…
- 譯者:Yangfan2016
JavaScript 是對值的接受是很是寬鬆的。例如在任何期待一個 number 類型的值的地方,它不會拒絕來自其餘類型的值,而是會試圖轉換它們:html
> '5' - '2'
3
> '5' * '2'
10
複製代碼
自動轉換成 boolean 值是不多出問題而且頗有用。這裏先埋下個伏筆(咱們將用它解決一些怪異問題)。然而,自動轉換爲 string 可能會形成一些問題git
無論什麼時候 JavaScript 接受一個 boolean 值時(例如,if 語句的條件),任何值均可以用。它要麼解釋爲 true,要麼解釋爲 false。下面的值都會被解釋爲 false:github
undefined, null
Boolean: false
Number: -0, +0, NaN
String: ''
複製代碼
其餘全部的值都會被看成 true。值被解釋爲 false 的稱做 falsy(假值),值被解釋爲 true 的稱做 truthy(真值)。你可使用 Boolean 函數來測試一個值會被解釋爲何。它會把它的參數轉換爲 boolean 值:web
> Boolean(undefined)
false
> Boolean(0)
false
> Boolean(3)
true
複製代碼
在 web 開發中,你會常常獲取到其實是 number 或 boolean 而看成 string 類型的值。例如,當用戶在表單輸入一些數據時。若是你忘記了顯式轉換這些 string 的話,JavaScript 會給你帶來兩個消極方面的驚喜:首先,不會有任何警告。其次,值會被自動轉換,可是是錯的。例如,操做符加號(+)就有問題,由於只要操做符的一邊是 string 類型的,它就會當成字符串鏈接符。在下面的例子中,假設咱們執行的是 1 和 5 相加,而實際上,咱們執行的是 ‘1’ 和 ‘5’ 字符串鏈接app
> var x = '5'; // 錯誤假設:x 是 number 類型
> x + 1
'51'
複製代碼
此外,還有一些極少數的 falsy 值,若是被轉換爲 string 類型的,就會被當成 truthy,例如:false函數
> Boolean(false) // truthy?
false
> String(false)
'false'
> Boolean('false') // truthy?
true
複製代碼
例如:undefined測試
> Boolean(undefined) // truthy?
false
> String(undefined)
'undefined'
> Boolean('undefined') // truthy?
true
複製代碼
若是 JavaScript 期待的是 number 或 string 類型的值的時候,object 纔會發生隱式轉換。第一種狀況下(期待 number),會按照三個步驟進行轉換:ui
譯者改:spa
譯者注:這裏注意 Date 對象(object)特殊,valueOf 和 toString 調用順序不一樣翻譯
第 1 步的例子:
> 3 * { valueOf: function () { return 5 } }
15
複製代碼
第 3 步的例子:
> function returnObject() { return {} }
> 3 * { valueOf: returnObject, toString: returnObject }
TypeError: 沒法將 object 轉換爲原始類型
複製代碼
若是是 JavaScript 轉換爲 string 類型,那步驟 1 和步驟 2 進行交換:首先試圖調用 toString() 方法,而後調用 valueOf() 方法
最好的辦法是在使用它們以前就顯式轉換爲指望的類型。一個迷你的解決方案是用 Boolean(),Number() 和 String() 方法:
function handleFormData(formData) {
var givenName = String(formData.givenName);
var age = Number(formData.age);
...
}
複製代碼
這些函數總會返回一個值(它們永遠都不會拋出異常)。然而 Number() 函數在它不能轉換一個值時會返回 NaN
[1]:
> Number('xyz')
NaN
> Number(undefined)
NaN
> Number(null)
0
> Number(true)
1
複製代碼
更詳細的解決方案是在你轉換這些值時,先檢查下它們的格式(例如,人們不能把 ‘xyz’ 做爲它們的年齡),若是不對,要採起適當的解決措施
感謝@hsy0 的評論,原文做者這裏沒有講清楚,畢竟一千我的一千個哈姆雷特,咱們仍是直接看標準吧 ecma-262/6.0/#sec-toprimitive
其實真實轉換過程以下(做者在另外一篇文章中提到了,😂,和標準一致),就不翻譯了
An object obj is converted to a number by calling ToPrimitive(obj, Number) and then applying ToNumber() to the (primitive) result. An object obj is converted to a number by calling ToPrimitive(obj, String) and then applying ToString() to the (primitive) result.