JavaScript類型轉換的迷糊事兒

最近在寫公司的登陸註冊模塊,遇到類型不一樣相比較的時候,就心驚膽戰,每次都要用瀏覽器來驗證一下,決定亂七八糟的隨便寫一下,方便往後本身回顧知識~正則表達式

弱類型帶來的那些讓人迷糊的事

弱類型帶來的好處之一:終於不用本身肯定數據類型了。數組

寫C++這類的強類型語言,每次都要先肯定是intchar仍是string之類的,可是僅僅經過var,怎麼解決工做過程當中的不一樣數據類型的比較問題的呢?瀏覽器

這個問題煩了我好久,當初學js的時候就只能記住最簡單的其餘類型到boolean的轉換,涉及到其餘的,只能暈菜。。。函數

下面分幾步來簡單的探探不一樣類型的轉換吧~性能

如下的內容,均可以從《JavaScript權威指南》中找到。學習

其餘值轉換成boolean

在編寫JavaScript代碼的過程當中,幾乎不用考慮它的取值類型。在工做過程當中,咱們有可能會須要在if的條件判斷中對參數進行判斷,這就涉及到了boolean值的轉換。spa

當JavaScript指望使用一個布爾值的時候,你能夠提供任意類型值,JavaScript將根據須要自行轉換類型,一些值(真值)轉爲true,其餘值(假值)轉爲false--《JavaScript權威指南》(page 48)prototype

對於布爾值類型的轉換,實際上只須要特別記住幾個特殊的會轉換成false的值就能夠了3d

這些值包括:undefinednullfalse""0-0NaNcode

全部的其餘值(包括全部對象)都會轉換成true

通常在工做中,咱們能夠直接使用:

if (value){
    ...
}

根據js的語言特性,可讓瀏覽器直接替咱們判斷,省時省力,我我的不太喜歡下面的寫法:

if (value == null){
    ...
}

儘管這樣也能夠達成目標,可是總感受多敲了代碼,還須要特別注意若是不是null或者undefined,但也是假值的狀況。

須要特別注意:假值中包含0 or -0的狀況

還有一個小點須要特別注意一下:jQuery中選擇符選擇某個DOM節點,也許這個DOM節點並不存在,可是$(selector)返回的值是一個對象,因此,咱們判斷是否存在這個DOM,須要經過$(selector).length > 0來判斷是否存在。

原始值轉換成字符串

原始值:數字字符串布爾值nullundefined

原始值轉換成字符串的狀況估計是最簡單的了,能夠直接理解成在原始值的兩邊加上""就好了

undefined --> "undefined"
null      --> "null"
true      --> "true"
false     --> "false"
0         --> "0"
-0        --> "-0"
NaN       --> "NaN"
Infinity  --> "Infinity"
-Infinity --> "-Infinity"
1         --> "1"
......

原始值轉換成數字

除了字符串,大部分原始值都會有固定的轉換結果,以下:

undefined  --> NaN
null       --> 0
true       --> 1
false      --> 0

可是,字符串的轉換有點微妙,給個人感受有點相似Number()方法,可是注意,只是相似,調用Number()會生成包裝對象,而不是一個數字。

字符串轉換成數字,會有如下的特色:

  1. 以數字表示的字符串能夠直接轉換成數字

  2. 容許字符串開頭跟結尾帶有空格

  3. 在開始和結尾處的任意非空格符都不會被當成數字直接量的一部分,轉換結果變成NaN

結果以下:

"one"  --> NaN
"u123" --> NaN
" 123" --> 123
"123 " --> 123
" 12 " --> 12

原始值轉換成對象

原理:原始值經過調用String()Number()Boolean()構造函數,轉換成他們各自的包裝對象

存取字符串、數字或者布爾值的屬性的時候建立的臨時對象叫作包裝對象,他只是偶爾用來區分字符串值和字符串對象、數字和數值對象以及布爾值布爾對象。一般,包裝對象只是被看作是一種實現細節,而不用特別關注。--《JavaScript權威指南》(page46)

可是nullundefined信仰比較堅決,就是不想轉成對象,從而,當將它們用在指望是一個對象的地方都會拋出一個錯誤throws TypeError

注意:只是在轉換的過程當中會拋出Error,在顯性建立對象的時候,不會報錯
new Object

對象轉換成原始值

對象轉換成原始值,能夠分紅如下三種:

  1. 對象轉換成boolean

  2. 對象轉換成字符串(object-to-string)

  3. 對象轉換成數字(object-to-number)

其中,對象轉換成boolean,規則很是簡單:全部的對象都轉換成true(包括包裝對象)

注意new Boolean(false)是一個對象,轉換成布爾值也是true

而對象轉換成字符串以及對象轉換成數字根據場景不一樣,有些複雜,在學習瞭解他們的轉換過程以前,先來看兩個函數:toString()以及valueOf()

一、在MDN中搜索toString,你會發現以下情形:
toString

若是細細查看,你會發現:全部的對象都有toString()方法,做用就是返回一個反映這個對象的字符串。

可是,這個方法返回的值有些時候不是那麼的好。

例如:Object.prototypr.toString()

默認狀況下,每一個對象都會從Object上繼承到toString()方法,若是這個方法沒有被這個對象自身或者更接近的上層原型上的同名方法覆蓋(遮蔽),則調用該對象的toString()方法時會返回"[object type]",這裏的字符串type表示了一個對象類型。

例如:

var o = new Object();
o.toString()    //返回[object Object]

不少類定義了不少特定版本的toString()方法:

  1. 數組類Array.prototype.toString()

  2. 函數類Function.prototype.toString()

  3. 日期類Date.prototype.toString()

  4. 正則類RegExp.prototype.toString()
    ······
    使用方法及返回結果以下:
    objecttoString

二、在MDN搜索valueOf,能夠獲得與toString類似的結果。

可是,這個方法的任務並無詳細的定義,我甚至沒法從MDN的描述中得出它與toString的區別。

JavaScript calls the valueOf method to convert an object to a primitive value. You rarely need to invoke the valueOf method yourself; JavaScript automatically invokes it when encountering an object where a primitive value is expected.

也許從下面的代碼中咱們能夠初窺一二:

[1,2,3].toString() // --> "1,2,3"
[1,2,3].valueOf() // --> [1, 2, 3]
(function(x){f(x);}).toString() // --> "function (x){f(x);}"
(function(x){f(x);}).valueOf() // --> function anonymous(x)
/\d+/g.toString() // -->"/\d+/g"
/\d+/g.valueOf() // --> /\d+/g
new Date(2010,0,1).toString() // --> "Fri Jan 01 2010 00:00:00 GMT+0800 (中國標準時間)"
new Date(2010,0,1).valueOf() // --> 1262275200000

根據上面的結果,能夠嘗試得出如下的結論:

對象是複合值,並且大多數對象沒法真正表示爲一個原始值,所以默認的`valueOf()`方法簡單地返回對象自己,而不是返回一個原始值

數組、函數以及正則表達式簡單地繼承了這個默認的方法,而日期類定義的valueOf()方法返回它的一個內部表示:1970年1月1日以來的毫秒數

有了上面的兩個方法,咱們就能夠進行對象到字符串以及對象到數字的轉換了。

對象到字符串的轉換的步驟以下:

  1. 若是對象具備toString()方法,那麼就調用這個方法,返回一個原始值,若是這個值自己不是字符串,JavaScript會將其轉換成字符串,並返回字符串的結果。

  2. 若是沒有toString()方法,或者這個方法不返回一個原始值,那麼調用valueOf()方法,返回一個原始值,若是這個值自己不是字符串,JavaScript會將其轉換成字符串,並返回字符串的結果。

  3. 不然JavaScript沒法從toString()或者valueOf()得到一個原始值,這時拋出一個類型錯誤。

對象到數字的轉換的步驟以下:

    1. 若是對象具備valueOf()方法,那麼就調用這個方法,返回一個原始值,若是這個值自己不是字符串,JavaScript會將其轉換成字符串,並返回字符串的結果。

  1. 若是沒有valueOf()方法,或者這個方法不返回一個原始值,那麼調用toString()方法,返回一個原始值,若是這個值自己不是字符串,JavaScript會將其轉換成字符串,並返回字符串的結果。

  2. 不然JavaScript沒法從toString()或者valueOf()得到一個原始值,這時拋出一個類型錯誤。

結束了?你還沒考慮應用呢!

因爲JavaScript是弱類型語言,因此咱們對於類型轉換的應用其實有許多。

例如:if判斷、+運算符以及==運算符等等

關於+

  1. 進行數字加法以及字符串鏈接操做

  2. 若是其中的一個操做數是對象,則將對象轉換成原始值

==也是js判斷中經常使用的涉及到類型轉換的一個運算符
關於==

  1. 若是兩個值類型相同,進行===比較

  2. 若是兩個值類型不一樣,他們可能相等,須要按照必定的規則來進行類型轉換並比較

==類型不一樣時的轉換規則:

  1. 若是一個值是null,另外一個值是undefined,則相等

  2. 若是一個是字符串,另外一個值是數字,則把字符串轉換成數字,進行比較

  3. 若是任意值是true,則把true轉換成1再進行比較;若是任意值是false,則把false轉換成0再進行比較

  4. 若是一個是對象,另外一個是數值字符串,把對象轉換成基礎類型的值再比較。對象轉換成基礎類型,利用它的toString或者valueOf方法。 js核心內置類,會嘗試valueOf先於toString能夠理解爲對象優先轉換成數字);例外的是DateDate利用的是toString轉換。非js核心的對象,經過本身的實現中定義的方法轉換成原始值

關於比較運算符<|>|<=|>=

  1. 若是操做數爲對象,那麼這個對象將轉換成原始值:若是valueof()返回一個原始值,那麼直接使用這個原始值。不然,使用toString()的轉換結果進行比較操做

  2. 在對象轉換成原始值以後,若是兩個操做數都是字符串,那麼將按照字母表的順序對兩個字符串進行比較,字母表的順序是指組成這個字符串的16位unicode字符的索引順序。注意:字符串比較是區分大小寫的,全部大寫的ASCII字母都小於全部小寫的ASCII字母

  3. 在對象轉換成原始值以後,若是至少有一個操做數不是字符串,那麼兩個操做數都將轉換成數字進行數值比較。0-0是相等的。Infinity比其餘任何數字都大(除了Infinity自己),-Infinity比其餘任何數字都要小(除了它自己)。若是其中一個操做數是(或轉換後是)NaN,那麼比較操做符老是返回false

加號運算符與比較運算符的區別

  1. 加法運算符更偏心字符串的操做,比較運算符更偏心數字

  2. 只有兩個操做數都是字符串,才進行字符串的比較

1+2 //加法,結果是3
"1"+"2" //字符串鏈接,結果是"12"
"1"+2  //字符串鏈接,結果是"12"
11 < 2 //數字的比較,結果是false
"11" < "3" //字符串比較,結果爲true
"11" < 3 // 數字比較,"11"轉換成11,結果爲false
"one" < 3 //數字的比較,"one"轉換成NaN,結果爲false

注意:<=以及>=在判斷相等的狀況的時候,並不依賴相等或者嚴格相等運算符的比較規則,它們只是簡單的不大於不小於

反思

昨天公司的一件事對個人觸動挺大的,公司裏面的兩個後臺爲了表單提交是用GET仍是POST爭吵了半個小時。有些時候,不經意就會忽略一些問題,好比代碼的質量,性能的提升,這些都是值得程序猿們深刻探究的問題。

記得有過這樣一句話「你對待技術的態度,就是你對待生命的態度」。

做爲一名小猿,繼續奮鬥去嘍~

相關文章
相關標籤/搜索