你不知道的JavaScript中的數值轉換

console.log(null == false);es6

開門見山,說出你的答案! 對,沒錯,答案是false! 讓咱們一探究竟吧!數組

規定

先來閱讀如下兩份規則:bash

嚴格相等 === :ui

全等操做符比較兩個值是否相等,兩個被比較的值在比較前都不進行隱式轉換。若是兩個被比較的值具備不一樣的類型,這兩個值是不全等的。不然,若是兩個被比較的值類型相同,值也相同,而且都不是 number 類型時,兩個值全等。最後,若是兩個值都是 number 類型,當兩個都不是 NaN,而且數值相同,或是兩個值分別爲 +0 和 -0 時,兩個值被認爲是全等的。spa

var num = 0;
var obj = new String("0");
var str = "0";
var b = false;

console.log(num === num); // true
console.log(obj === obj); // true
console.log(str === str); // true

console.log(num === obj); // false
console.log(num === str); // false
console.log(obj === str); // false
console.log(null === undefined); // false
console.log(obj === null); // false
console.log(obj === undefined); // false
複製代碼

相等運算== :3d

The comparison x == y, where x and y are values, produces true or false.code

  1. 若是x不是正常值(好比拋出一個錯誤),中斷執行。
  2. 若是y不是正常值,中斷執行。
  3. 若是Type(x)與Type(y)相同,執行嚴格相等運算x === y。
  4. 若是x是null,y是undefined,返回true。
  5. 若是x是undefined,y是null,返回true。
  6. 若是Type(x)是數值,Type(y)是字符串,返回x == ToNumber(y)的結果。
  7. 若是Type(x)是字符串,Type(y)是數值,返回ToNumber(x) == y的結果。
  8. 若是Type(x)是布爾值,返回ToNumber(x) == y的結果。
  9. 若是Type(y)是布爾值,返回x == ToNumber(y)的結果。
  10. 若是Type(x)是字符串或數值或Symbol值,Type(y)是對象,返回x == ToPrimitive(y)的結果。
  11. 若是Type(x)是對象,Type(y)是字符串或數值或Symbol值,返回ToPrimitive(x) == y的結果。
  12. return false。

那麼咱們提煉如下規則:cdn

  1. 若是 x或者y不是正常值,中斷執行。
  2. 若是 typeof x 和typeof y相同,執行x === y。
  3. 若是 x和y分別是null和undefined,返回true。
  4. 若是 x和y分別是數值和字符串類型,那麼返回 x == Number(y) (y 爲字符串)
  5. 若是 x和y其中一個爲布爾類型,那麼返回x == Number(y) (若 x 爲布爾類型)
  6. 若是 x和y分別是(Symbol值 或 數值 或 字符串) 和 對象,返回x == ToPrimitive(y) (若 y 爲對象)
  7. return false

一、將值轉爲原始值,ToPrimitive()。對象

二、將值轉爲數字,ToNumber()。blog

三、將值轉爲字符串,ToString()。

1.ToPrimitive()

js引擎內部的抽象操做ToPrimitive有着這樣的簽名: ToPrimitive(input, PreferredType?) input是要轉換的值,PreferredType是可選參數,能夠是Number或String類型。他只是一個轉換標誌,轉化後的結果並不必定是這個參數所值的類型,可是轉換結果必定是一個原始值(或者報錯)。

1.1若是PreferredType被標記爲Number,則會進行下面的操做流程來轉換輸入的值。

一、若是輸入的值已是一個原始值,則直接返回它
二、不然,若是輸入的值是一個對象,則調用該對象的valueOf()方法,
   若是valueOf()方法的返回值是一個原始值,則返回這個原始值。
三、不然,調用這個對象的toString()方法,若是toString()方法返回的是一個原始值,則返回這個原始值。
四、不然,拋出TypeError異常。
複製代碼

1.2若是PreferredType被標記爲String,則會進行下面的操做流程來轉換輸入的值。

一、若是輸入的值已是一個原始值,則直接返回它
二、不然,調用這個對象的toString()方法,若是toString()方法返回的是一個原始值,則返回這個原始值。
三、不然,若是輸入的值是一個對象,則調用該對象的valueOf()方法,
   若是valueOf()方法的返回值是一個原始值,則返回這個原始值。
四、不然,拋出TypeError異常。
複製代碼

既然PreferredType是可選參數,那麼若是沒有這個參數時,怎麼轉換呢?PreferredType的值會按照這樣的規則來自動設置:

一、該對象爲Date類型,則PreferredType被設置爲String
二、不然,PreferredType被設置爲Number
複製代碼

toString()valueOf() 的用法有待補充。

2.ToNumber()

根據參數類型進行下面轉換:

參數 結果
undefined NaN
null +0
布爾值 true轉換1,false轉換爲+0
數字 無須轉換
字符串 有字符串解析爲數字,例如:‘324’轉換爲324,‘qwer’轉換爲NaN
對象 先進行 ToPrimitive(obj, Number)轉換獲得原始值,在進行ToNumber轉換爲數字

3.ToString()

根據參數類型進行下面轉換:

參數 結果
undefined 'undefined'
null 'null'
布爾值 轉換爲'true' 或 'false'
數字 數字轉換字符串,好比:1.765轉爲'1.765'
字符串 無須轉換
對象 先進行 ToPrimitive(obj, String)轉換獲得原始值,在進行ToString轉換爲字符串

Object.is():

Object.is() 判斷兩個值是否相同。若是下列任何一項成立,則兩個值相同:

  • 兩個值都是 undefined
  • 兩個值都是 null
  • 兩個值都是 true 或者都是 false
  • 兩個值是由相同個數的字符按照相同的順序組成的字符串
  • 兩個值指向同一個對象
  • 兩個值都是數字而且
  • 都是正零 +0
  • 都是負零 -0
  • 都是 NaN
  • 都是除零和 NaN 外的其它同一個數字

這種相等性判斷邏輯和傳統的 ==運算符所用的不一樣,==運算符會對它兩邊的操做數作隱式類型轉換(若是它們類型不一樣),而後才進行相等性比較,(因此纔會有相似 "" == falsetrue 的現象),但 Object.is 不會作這種類型轉換。

這與===運算符也不同。===運算符(和==運算符)將數字值-0+0視爲相等,並認爲Number.NaN不等於NaN。 示例:

Object.is('foo', 'foo');     // true
Object.is(window, window);   // true

Object.is('foo', 'bar');     // false
Object.is([], []);           // false

var test = { a: 1 };
Object.is(test, test);       // true

Object.is(null, null);       // true

// 特例
Object.is(0, -0);            // false
Object.is(-0, -0);           // true
Object.is(NaN, 0/0);         // true
複製代碼

實際運用

咱們先看如下如下幾種值比較的結果:

這裏寫圖片描述

挑選重點來分析以下:

[1,2] == "1,2" //true
複製代碼

左邊數組類型爲Obeject,右邊是String,知足總結條件6。 執行ToPrimitive([1,2]),在沒有參數的狀況下且不爲Date類型,轉換類型自動爲Number 再執行 [1,2].valueOf(),類型仍是Obeject,不爲原始值 再執行[1,2].toString()"1,2" 爲字符串原始值 最後比較"1,2" == "1,2",返回true

開始的那個問題:

null == false; //false
複製代碼

由於false是Boolean類型,知足總結中的第五條,因此實際比較

Number(bull) == false;
0 == null;
//false
複製代碼

最新的 ECMAScript 標準定義了 7 種數據類型: 6 種 原始類型: Boolean Null Undefined Number String Symbol (ECMAScript 6 新定義) 和 Object

0 == null null的類型是Null,實際上這個比較不知足轉換的任何一條規則,因此返回false

0 == NaN; //false
複製代碼

兩邊都是Number類型,因此比較全等=== 返回false

NaN == NaN; //false
複製代碼

從數值的角度上講NaN不與任何值相等。

相關文章
相關標籤/搜索