js中抽象相等==

Javascript中抽象相等比較算法

undefined==null
//true
[]==[]
//false
[]==![]
//true
{}==!{}
//false
![]=={}
//false
[]==!{}
//true
[1,2]==![1]
//false

大體介紹一下JS的數據類型

ES5的數據類型分爲6種:Undefined Null String Number Boolean Object,若是再加上ES6Symbol數據類型,一共7種;git

nullundefined的區別:github

  1. null描述一個空值(空的對象引用即空指針),null被當作一個對象,typeOf null輸出爲'Object'(算是一個bug吧),Number(null)輸出爲0undefined是預約義的全局變量,表示「缺乏值」,typeOf undefined輸出爲'undefined'Number(undefined)輸出爲NaN
  2. null是一個關鍵字,而undefined並非一個關鍵字;

原始值概念

js的數據類型其實能夠分爲兩種:原始類型引用類型原始類型又稱簡單類型基本類型,包括UndefinedNullBooleanNumberString五種。引用類型又稱複雜類型,即Object原始類型引用類型分別稱爲原始值複雜值算法

簡單的說:原始值是固定而簡單的值,是存放在棧(stack)中的簡單數據段,也就是說,它們的值直接存儲在變量訪問的位置,原始類型的值被稱爲原始值函數

原始類型(primitive type)有如下五種類型:Undefined,Null,Boolean,Number,String.net

typeOf運算符:指針

條件 返回值
若是變量是undefined類型 undefined
若是變量是Boolean類型 boolean
若是變量是Number類型 number
若是變量是String類型 string
若是變量是Null類型 object
若是變量是引用類型 object

抽象相等算法

用Type(z)表明z的數據類型,比較運算 x==y,其中x和y是值,產生true或false。
    1.Type(x)與Type(y)相同:
        a.若是Type(x)爲Undefined或Null,則返回true
           
        b.若是Type(x)爲Number,則:
            i.若x爲NaN,返回false
            ii.若y爲NaN,返回false
            iii.若x與y數值相等,返回true
            iiii.若x爲+0,y爲-0,返回true
            iv.若x爲-0,y爲+0,返回true
            v.返回false
            
        c.若是Type(x)爲String,則x和y對應位置的字符徹底同樣才返回true,不然返回false,
        
        d.若是Type(x)爲Boolean,則相同值返回true,不然false
        
        f.當x和y引用同一對象時,返回true,不然,返回false
            
    2.x爲undefined,y爲null,返回true,反之亦然
            
    3. Type(x)爲String,Type(y)爲Number,則返回比較ToNumber(x) == y,反之亦然
            
    4.Type(x)爲Boolean,則返回比較ToNumber(x)==y的結果,反之亦然

    5.Type(x)爲String或Number,Type(y)爲Object,則返回比較ToPrimitive(y) == x
    
    6.返回false

再來看看ToBooleanToNumberToPrimitive三個運算符的定義:code

ToBoolean
輸入類型 結果
Undefined false
Null false
Boolean 不轉換
Number 若是參數是-0+0NaN,結果爲false,不然爲true
String 若是參數是空字符串(長度爲零),結果爲false,不然爲true
Object true
ToNumber
輸入類型 結果
Undefined NaN
Null +0
Boolean 參數爲true,結果爲1,參數爲false,結果爲+0
Number 不轉換
String 參見下文的文法和註釋
Object 應用下步驟:一、設原始值爲ToPrimitive(輸入參數,暗示,數值類型)。二、返回ToNumber(原始值)
ToPrimitive

ToPrimitive運算符接收一個值,和一個可選的指望類型做參數。ToPrimitive運算符把其值參數轉換爲非類型對象。若是對象有能力被轉換爲不止一種原語類型,可使用可選的 指望類型 來暗示那個類型。對象

輸入類型 結果
Undefined 不轉換
Null 不轉換
Boolean 不轉換
Number 不轉換
String 不轉換
Object 返回該對象的默認值。對象的默認值由指望類型傳入做爲hint參數調用對象內部方法[DefaultValue]獲得

** ToPrimitive這個方法,參照火狐MDN上的文檔介紹,大體意思以下:blog

ToPrimitive(obj,preferredType)ip

JS引擎內部轉換爲原始值ToPrimitive(obj,preferredType)函數接受兩個參數,第一個obj爲被轉換的對象,第二個
preferredType爲但願轉換成的類型(默認爲空,接受的值爲Number或String)

在執行ToPrimitive(obj,preferredType)時若是第二個參數爲空而且obj爲Date的實例時,此時preferredType會
被設置爲String,其餘狀況下preferredType都會被設置爲Number若是preferredType爲Number,ToPrimitive執
行過程如
下:

  1. 若是obj爲原始值,直接返回;
  2. 不然調用 obj.valueOf(),若是執行結果是原始值,返回之;
  3. 不然調用 obj.toString(),若是執行結果是原始值,返回之;
  4. 不然拋異常。

若是preferredType爲String,將上面的第2步和第3步調換,即:

  1. 若是obj爲原始值,直接返回;
  2. 不然調用 obj.toString(),若是執行結果是原始值,返回之;
  3. 不然調用 obj.valueOf(),若是執行結果是原始值,返回之;
  4. 不然拋異常

Ok,到如今,咱們須要瞭解,toString方法和valueOf方法;

toString用來返回對象的字符串表示。

let obj = {name:"Tom"}; //"[object Object]"
    let obj = {}; //"[object Object]"
    let arr = [1,2];    //"1,2"
    let arr = [];    //""
    let str = "1";      //"1"
    let num = 1;        //"1"
    let boo = true;     //"true"
    let date = new Date();      //"date Sat Mar 24 2018 00:23:12 GMT+0800 (CST)"
    let nul = null;     //報錯
    let und;            //報錯

valueOf方法返回對象的原始值,多是字符串數值bool值等,看具體的對象。

let obj = {name:"Tom"}; //{name:"Tom"}
    let arr = [1,2];    //[1,2]
    let str = "1";      //"1"
    let num = 1;        //1
    let boo = true;     //true
    let date = new Date();      //1521822331609
    let nul = null;     //報錯
    let und;            //報錯

簡單理解:原始值指的是[Null,Undefined,String,Boolean,Number]五種基本數據類型之一

總結一下==運算的規則:

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

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

3. String/Boolean == Number,須要String/Boolean轉爲Number。

4. Object == Primitive(原始值),須要Object轉爲Primitive(具體經過valueOf和toString方法)。

栗子

undefined==null
//true
[]==[]
//false
[]==![]
//true
{}==!{}
//false
![]=={}
//false
[]==!{}
//true
[1,2]==![1]
//false

undefined==null

結果爲true,不用解釋了,記住就好了

[]==[]

  1. 先看這兩個的類型,typeOf([])獲得的是'object'
  2. 抽象相等算法1-f,引用同一類型的纔算相等
  3. 返回false

[]==![]

  1. !取反運算符的優先級高於==,所以先算出![]這個得值,再去使用抽象相等算法進行比較
  2. 取反運算符會先調用方法ToBoolean,再去取反
  3. ToBoolean([])返回的是true,所以![]應該爲false
  4. []==![]轉換爲了[]==false
  5. 根據抽象相等算法4條,則咱們能夠比較[]==ToNumber[false]的值,則能夠獲得[]==0
  6. 再根據抽象相等算法5條,比較ToPrimitive([])==0
  7. 因爲[]不是Date類型,因此先獲得[].valueOf()的值,爲[]
  8. 再獲得[].toString()的值,爲""的字符串
  9. 以上7,8部可合併爲一步即比較[].valueOf().toString(),獲得""字符串,此時[]轉換爲了原始值類型(即五種基本類型中的一種)了。
  10. 根據抽象相等算法3,則能夠比較ToNumber("")==0,到這裏[]==![]轉化爲了0==0
  11. 返回true

{}==![]

  1. 表達式右側,重複上一次的1-5步,能夠獲得{}==0
  2. 根據抽象相等算法5條,ToPrimitive({})==0,獲得{}.valueOf().toString()獲得一個字符串"[object Object]",是原始類型
  3. 根據抽象相等算法3,最後比較ToNumber("[object Object]")==0,轉變爲1==0
  4. 返回false

...

其他的栗子本身算一算吧

結語

本身從新寫了寫一遍整理了一下思路,若是什麼地方沒有講清楚,請指出;

參考:

相關文章
相關標籤/搜索