Javascript中
讓人詬病的技術點很多,類型轉換就是其一,甚至《Javascript
語言精粹》的做者Douglas Crockford
直接將Javascript
中的類型轉換歸爲糟粕、雞肋(PS:聽說做者在平常開發中也常用到Javascript
這一特性,看來萬事逃不過真香定律啊)。而類型轉換中最讓人詬病的就數+ 、 ==
操做過度了。可是Javasript
的類型轉化也不是一無用處。爲了讓你們在開發過程當中用的舒心、放心,因而就有了這篇博文。但願對你們有幫助。html
❝這裏直接上各類類型之間的轉換結果,若是沒有明白,那就帶着問題往下讀。web
❞
1 + "1" // '11'
1 + "string" // "1tring" (加非數字字符串) 1 + true // 2 1 + false //1 1 + [] // "1" 1 + [1,2,3] // "11,2,3" 1 + {} // "1[object Object]" 1 + null // 1 1 + undefined // 1 null + undefined // NaN true + 1 // 2 true + "1" // "true1" true + "true" // "truetrue" (加非數字字符串) true + true // 2 true + false // 1 true + [] // "true" true + [1,2,3] // "true1,2,3" true + "true[object Object]" // NaN true + null // 1 true + undefined // NaN false + 1 // 1 false + "1" // "false1" false + "string" // "falsestring" (加非數字字符串) false + false // 0 false + true // 1 false + [] // "false" false + {} // "false[object Object]" [] + 1 // "1" [] + "1" // "1" [] + "string" // "string" (加非數字字符串) [] + true // "true" [] + false // "false" [] + [] // "" [1] + [1] // "11" [] + {} // "[object Object]" (注意!!!) [] + null // "null" [] + undefined // "undefined" {} + 1 // 1 {} + "1" // 1 {} + "string" // NaN {} + true // 1 {} + false // 0 {} + [] // 0 (注意!!!) { a:1 } + [] // 0(注意!!!) {} + [1] // 1 (注意!!!) {} + [1,2,3] // NaN (注意!!!) {} + {} // "[object Object][object Object]" {} + null // 0 {} + undefined // NaN -Infinity + Infinity // NaN 複製代碼
「總結」數組
ToPrimitive
操做,該抽象操做再調用
[[DefalutValue]]
,以數字做爲上下文,保證了優先調用
valueOf()
方法,可見在 + 操做時,引用類型內部調用
valueOf()
方法的
「優先級」高於
toString()
。
valueOf()
方法若是沒法獲取到基本類型值(數字),會轉而調用
toString()
。
「代碼演示」編輯器
// 這裏提供valueOf()方法,
var daRui = { valueOf: function() { return 18 }, toString: function() { return "daRUI" } } daRui + 7 // 25 daRui + "7" // "187" daRui + "hello" // "18hello" // 這裏僅提供toString()方法, var daRui = { toString: function() { return "daRUI" } } daRui + 7 // "daRUI7" daRui + " hello" // "daRUI hello" 複製代碼
「特別說明」flex
toString()
方法是通過改寫的,故
[1,2,3]
會轉爲"1,2,3",
[]
會轉爲""。
toString()
方法會返回 "[object Class]",
Object.prototype.toString.call([])
返回 "[object Array]"。
[] + {}
獲得」[object Object]「,而
{} + []
獲得 0。這是由於
{}
(花括號)在JS中有兩種含義:
{}
在 + 後面時,表示對象
{}
{}
位於 + 前面時,
{}
表示一個獨立的
「空代碼塊」,因此
{} + []
操做至關於進行的是
+[]
(一元操做符轉換操做) 將
[]
轉爲0
1 == '1' // true
1 == true // true 1 == [] // false 1 == [1] // true 1 == {} // false true == "1" // true true == "true" // false true == [] // true true == [1] // true true == {} // false [] == "1"// false [] == true // false [] == false // true [] == [] // false [] == {} // false [] == ![] // true (注意!!!) {} == 1 // Unexpected token '==' {} == "1" // Unexpected token '==' {} == true // Unexpected token '==' {} == false // Unexpected token '==' {} == [] // Unexpected token '==' {} == {} // false "0" == null // false "0" == undefined // false "0" == false // true (注意!!!) "0" == NaN // false "0" == 0 // true "0" == "" // false false == null // false (注意!!!) false == undefined // false (注意!!!) false == NaN // false false == 0 // true (注意!!!) false == "" // true (注意!!!) false == [] // true (注意!!!) false == {} // false "" == null // false "" == undefined //false "" == NaN // false "" == 0 //true (注意!!!) "" == [] // true (注意!!!) "" == {} // false 0 == null // false 0 == undefined // false 0 == NaN // false 0 == [] // true (注意!!!) 0 == {} // false +0 == -0 // true null == null // true null == undefined // true null == "" // false null == 0 // false undefined == "" // false undefined == 0 // false NaN == NaN // false 可使用isNaN() 判斷是否是NaN 複製代碼
「總結」ui
== 操做,最重要的時在兩個操做數的轉換過程!關於 == 操做ES5 規範11.9.3給出了明確規範:url
x == ToNumber(y)
的結果。
ToNumber(x) == y
的結果。
ToNumber(x) == y
的結果
x == ToNumber(y)
的結果
x == ToPrimitive(y)
的結果
toPrimitive(x) == y
的結果
❝== 相等操做中,若是兩邊的操做數不一樣的話,都會進行類型轉換,並且優先轉爲數字,再進行比較,若是轉換後還不一樣則再次轉換,直到相同爲止。這裏以
字符串類型 == 布爾類型
作介紹:spa
首先字符串類型轉爲Number 類型,這時比較的是 數字類型 == 布爾類型
再將布爾類型轉爲Number類型,這時比較的是 數字類型 == 數字類型
這也就不難解釋爲何
"0" == false
了prototype若是連個操做數中有引用類型,這會先將引用類型轉換爲基本類型,在進行上面的操做,進行比較。設計
再說
[] == ![] // true
:❞
這裏!操做的優先級是高於 == 的,![] 首先轉換爲false 此時比較雙方是 [] == false,這裏會將 [] 再次轉換爲 0 此時比較雙方是 0 == false,接下來就不難理解了
❝&&與||邏輯運算符的特殊之處在於,二者返回的是兩個操做數中的一個(且僅一個),即選擇兩個操做數中的一個,而後返回它的「值」。這兩個邏輯運算符首先會對第一個操做數執行條件判斷,若是其不是布爾值就先進行
ToBoolean
強制類型轉換,而後在執行條件判斷。對於||來講,若是條件判斷結果爲true就返回第一個操做數的值,若是爲false就返回第二個操做數的值。
&&則相反,若是條件判斷結果爲true就返回第一個操做數的值,若是爲false就返回第一個操做數的值。 ——《你不知道的Javascript上卷》
❞
18 || "daRui" // 18
undefined || "daRui" // "daRui" 18 && "daRui" // daRui null && "daRui" // null null || {} // {} null && {} // null 複製代碼
「總結」
||與&&返回的都是操做數中兩個中的一個,這個嚴格意義上說並非一種轉換,而是一種選擇
平常開發中的 if (a||b) {return true}
的過程,實際上是先獲取到 a||b
的值再進行的判斷
這裏說 ||和&&的緣由是它能夠簡化咱們平常開發中的代碼,使代碼更簡潔,例:
18 || "daRui"
// 至關於 18 ? 18 : "daRui" 18 && "daRui" // daRui // 至關於 18 ? "daRui" : 18 複製代碼
將值轉爲布爾值
// 除將下面的轉爲false其他所有爲true
!! "" !! 0 !! -0 !! +0 !! null !! undefined !! NaN 複製代碼
❝每一個人都有一個覺醒期,但覺醒的遲早決定我的的命運。 ——路遙
❞
參考文獻:
Javascript
》中卷
Javascript
高級程序設計》
Javascript
》
本文使用 mdnice 排版