js == 運算規則解析

1.先了解一下基本類型和複雜類型劃分的依據

JS中的值有兩種類型:原始類型(Primitive)、對象類型(Object)。原始類型包括:Undefined、Null、Boolean、Number和String等五種。這兩大類別的數據存儲方式是不同的。javascript

存儲空間的時空關係能夠歸納爲空間大,訪問起來就慢,反之亦然。堆比棧大,棧比堆的運算速度快,html

對象是一個複雜的結構,而且能夠自由擴展,如:數組能夠無限擴充,對象能夠自由添加屬性。將它們放在堆中是爲了避免影響棧的效率。而是經過引用的方式查找到堆中的實際對象再進行操做。java

相對於對象類型而言,原始類型就比較穩定,而且它只佔據很小的內存。不將原始類型放在堆是由於經過引用到堆中查找實際對象是要花費時間的,而這個綜合成本遠大於直接從棧中取得實際值的成本。因此簡單數據類型的值直接存放在棧中。`數組

順帶說一下undefined和null的使用區別:

假如你打算把一個變量賦予對象類型的值,可是如今尚未賦值,那麼你能夠用null表示此時的狀態(證據之一就是typeof null 的結果是'object');相反,假如你打算把一個變量賦予原始類型的值,可是如今尚未賦值,那麼你能夠用undefined表示此時的狀態。ui

 

2.進行==比較時數據的轉換規則

 ==運算規則的準備描述以下:spa

看完以後有沒有感受有點腦袋疼,這樣的描述很難讓人在實踐中使用,因此頗有必要對上述規則進行簡化歸納:3d

  • undefined == null,結果是true。且它倆與全部其餘值比較的結果都是false。code

  • String == Boolean,須要兩個操做數同時轉爲Number。htm

  • String/Boolean == Number,須要String/Boolean轉爲Number。對象

  • Object == Primitive,須要Object轉爲Primitive(具體經過valueOf和toString方法)。

 

 

 

 那麼Boolean,Number,Primitive的轉換規則是:

(1)其它類型轉換成Boolean的規則是:

(2)其它類型轉換成Number類型的規則

object類型通常要先轉換成string類型,接着才進行Number類型的轉換。字符串轉化爲數字的規則規範中描述得很複雜,可是大體說來,就是把字符串兩邊的空白字符去掉,而後把兩邊的引號去掉,看它可否組成一個合法的數字。若是是,轉化結果就是這個數字;不然,結果是NaN。

Number('123') // 結果123
Number('1.2e3') // 結果1200
Number('123abc') // 結果NaN
Number('\r\n\t123\v\f') // 結果123

固然也有例外,好比空白字符串轉化爲數字的結果是0。即:

Number('') // 結果0
Number('\r\n\t \v\f') // 結果0
須要補充說明的是:
(3)對象類型向primitive類型轉換的規則是:

     爲何要區分原始類型和複雜類型?

     原始類型是一種單純的類型,它們直接了當、容易理解。然而缺點是表達能力有限,難以擴展,因此就有了對象。對象是屬性的集合,而屬性自己又能夠是對象。因此對象能夠被構造得任意複雜,足以表示各類各樣的事物。

  可是,有時候事情複雜了也不是好事。好比一篇冗長的論文,並非每一個人都有時間、有耐心或有必要從頭至尾讀一遍,一般只瞭解其中心思想就夠了。因而論文就有了關鍵字、概述。JavaScript中的對象也同樣,咱們須要有一種手段瞭解它的主要特徵,因而對象就有了toString()和valueOf()方法。

     這兩種方法的區別是:

toString()方法用來獲得對象的一段文字描述;而valueOf()方法用來獲得對象的特徵值。

   toString()方法傾向於返回一個字符串。valueOf()方法傾向於返回一個數字——儘管內置類型中,valueOf()方法返回數字的只有Number和Date。


對於全部非日期對象來講,對象到原始值的轉換基本上是對象到數字的轉換

  通常來講,對象到數字的轉換通過了以下過程:

  1.若是對象具備valueOf()方法,後者返回一個原始值,則js將這個原始值轉換成數字,並返回這個數字。

  2.不然,若是對象具備toString()方法,後者返回一個原始值,則js將轉換並返回。(首先js轉換成相應的字符串原始值,再繼續將這個原始值轉換成相應的數字類型,再返回數字)

  3.不然,js拋出一個類型錯誤異常。

  通常來講,對象到字符串的轉換通過了以下步驟:

  1.若是對象具備toString()方法,則調用這個方法。若是它返回一個原始值,js將這個值轉換成字符串,並返還這個字符串結果。

  2.若是對象沒有toString()方法,或者toString並不返回一個原始值,那麼js將調用valueOf()方法。

  3.不然,js沒法從toString()或者valueOf()得到一個原始值,所以這時它將拋出一個類型錯誤異常。

 
下圖第一列和第二列是其它類型調用toString方法時的轉換規則

    須要說明的是: toString方法會將{}轉換成"[object Object]",將function(){}轉換成"function(){}"

 

    其它類型調用valueOf方法的轉換規則是:

 

    通過層層深刻剖析,如今你應該理解前面各類數據類型進行 == 運算時的隱式運做規則了吧。如今再碰到以下的問題,是否是感受思路很清晰

 

[]==[]             //false []==![] //true {}==!{} //false 實際上被解析成 { ' } == !{ ' } {}==![] //Uncaught SyntaxError: Unexpected token == 表達式不能以{開頭 {}是個語句塊,後面跟== ![]就變成了一種語法錯誤的語句塊
// 在語法解析的時候,若是一個語句以「{」開頭,就只把它解釋成語句塊。換用形式語法的說法,就是「表達式語句不能以『{』開頭」。對錶達式語句開頭的另外一個限制——限制「function」出如今開頭——同理。 ![]=={} //false []==!{} //true undefined==null //true

一張圖完全搞懂JavaScript的==運算 []  == []  // false 由於它們的引用地址不同

由上面的比較能夠得出:
對任何一種類型進行取反 會獲得一個boolean類型的值
[]在與不一樣的類型對比的時候,會轉換成0
{}在與不一樣的類型對比的時候,會轉換成NaN,
不一樣類型的比較最終都被轉換成number類型的比較

參考文章

[1]

    [2] 爲何控制檯打印{}+[]===[]+{}爲false?

相關文章
相關標籤/搜索