Javascirpt世界裏,不推薦大量的使用try...catch...,我想大概緣由:前端
JS裏任何類型之間的算數運算,邏輯運算和位運算都不會拋異常或者錯誤。例如 1/0 == Infinity, 0/0 = NaN, [ ] + 1 = '1' 等。因此catch到excepton/error的概率,相對於編譯型語言甚至於python/ruby等動態語言,是大大地下降了。python
try...catch...會在catch裏轉換到一個新的做用域,catch裏面調用本函數或者函數外的對象時,增長了一層做用域的查找,下降了運行效率web
若是有未知的風險,確實能夠try...catch...。可是若是你的代碼裏有比較多的try...catch...,這就是bad smell,說明須要增強coding質量或者重構了。typescript
這裏討論JS裏對不一樣類型進行運算的時候,是如何作類型轉換的(通常是隱式轉換)。編程
1 + '-1' = '1-1'
基本類型之間相加時,只要其一是字符串,另一個也會先轉換爲字符串,結果就變成字符串的鏈接。後端
[ ] + 1 = '1'
引用類型和基本類型相加。引用類型先轉化爲基本類型。轉化過程:先查看對象的valueOf()方法是否返回基本類型。數組的valueOf返回它自己,屬於object類型,不是基本類型。因此再調用toString方法。空數組[]的toString返回空字符串。結果轉爲‘’ + 1. 返回字符串‘1’。數組
[ ] + { } = [object Object]
引用類型之間的加法。引用類型需先轉換爲基本類型。 參考2,空數組[]轉爲空字符串。相似地空對象{ } 轉換時,也先查看{ }.valueOf(). 由於 {}的valueof方法返回它自身,因此會調用{}.toString()返回‘[object Object]'。
這樣結果變成 '' + '[object Object]' = '[object Object]'ruby
1 + null = 1
由於已是基本類型,並且沒有字符串,因此會基於number類型運算。 null轉爲0, 結果是 1 + 0 = 1函數
1 + undefined = NaN
undefined 轉爲NaN, so 1+ NaN = NaN學習
false + null = 0
都是基本類型並且沒有字符串,因此基於數字類型相加。 false轉爲0, null也爲0. 結果 0 + 0 = 0
[1] + [2] = '12'
分別調用toString方法以轉爲基本類型,獲得'1'和‘2’, '1' + '2' = '12'
加法之外的算數運算,若是有object類型(包括數組),先轉爲基本類型,這和加法運算是相同的。轉換過程也是先查看valueOf是否返回基本類型,若是不是,就調用toString(這裏假定toString都返回string。除非誰閒着沒事,非得給一對象的toString返回對象類型?)
和加法運算不一樣的是,轉換爲基本類型後,全部的基本類型再轉爲number類型,最終以number類型進行運算。
1 - "-1" = "-1"
字符串「-1」轉爲number的-1, 結果1 - (-) = 2
[ ] - 1 = -1
[ ]先轉爲基本類型,是空字符。空字符再轉爲number爲0 ,結果是0 - 1 = -1
[ ] / { }
空數組轉爲基本類型是空字符,空對象轉爲基本類型是[object Object],兩者再分別轉爲數字類型是 0 和 NaN,最終結果爲0/NaN = NaN
1 / null
都已經爲基本類型,因此只要把null轉爲number類型的0, 而後1 / 0 = Infinity
1 * undefined
都已經爲基本類型,因此只要把undefined轉爲number類型的NaN, 而後1 * NaN = NaN
1 && null = null
.
由於1 是真值,則返回第二個值, 即null
null && undefined = null
返回null,由於null是falsy,則返回第一個。
0 || {} = {}
返回 {}. 由於0 是falsy,返回第二個
1 || null = 1
返回1, 由於1是真值,返回第一個
~n = -(n+1)
,
例如~25 = -26. 這裏是帶符號的取反。若是是無符號的取反,結果就不同了,有興趣的能夠在C語言裏試試 ~25u
~null = -1
null轉爲0, ~0 = -(0+1) =-1
~undefined
//SyntaxError: Invalid or unexpected token
~~23.5 = 23
~~-23.5 = -23
但 Math.floor(-23.5) = -24. 故而通常用~~取整數位
if(-1)
和if (-1 == true)
是不同的。前者是真假判斷: -1是truthy,是真值。後者相似算術運算:先轉爲number,true 轉爲1, 故而 -1 == 1是假值。
這裏總結了js類型轉換和運行的基本規律,但願是能夠知足基本的項目須要了。
JS不一樣類型之間的類型轉換,確實是讓人撓頭的語言。我猜測多是JS產生的時候,web方興未艾,web工程師的編程功底尚未很規範(至少沒有今天這麼多資料書籍和培訓機構等),因此js容許類型轉換,不一樣類型之間運算時,保證不拋異常或者儘可能少拋。
可是如今前端和後端同樣的龐大了,顯然js的這樣那樣的技法每每會使工程師掉入陷阱。typescript應允而生,一個目的是也是幫助初級工程師寫出還能夠的代碼(另一個目的估計是下降後端開發者寫前端的門檻和思惟轉變)。從這角度解讀,ts也是爲知足項目工程和公司的須要。若是想深刻js學習,原生的js(es5/6)是繞不開的。
前面提到「try...catch...會在catch裏轉換到一個新的做用域」,這是在《你不知道的JavaScript》中卷裏看到的。後來感受仍是作些論證,不然老以爲不踏實。看以下代碼:
function testException() { var error = 'outer error' try { throw 'inner error' } catch (error) { console.log(error) error = 'modify inner error' } // 這裏會輸出 outer error(而不是modify inner error), // 說明catch...裏修改的error,不是testExecution()函數做用域裏的,而是一個「新」做用域裏的error // 因此咱們可認爲,catch...建立了一個新的做用域。看來它和函數做用域的相似點,都接受「參數」 console.log(error) } testException()