Java Script 中 ==(Equal) 和 === (Identity Equal) 的區別和比較算法邏輯

判斷兩個變量是否相等在任何編程語言中都是非常重要的功能。

JavaScript 提供了 == 和 === 兩種判斷兩個變量是否相等的運算符,但我們開始學習的時候 JavaScript 的時候,就被一遍又一遍的告知:

  • === 要求變量的類型和值均相等,才能返回true。
  • 使用 === 來避免因JavaScript 類型轉換帶來的問題。

這樣增加了 JavaScript 語法的靈活性但是也帶來很多頭疼的問題:

  • 使用 ==/!=是 ===/!== 來判斷兩個變量是否相等?
  • 為什么,JS 編碼推薦使用 ===/!= 而不是 ==/!=,大部分的編程語言不都是使用==/!=么?

為了要回答這個問題,讓我們看一下 JavaScript 所遵守的標準 ECMAScript 對于==和 === 是怎么描述的吧!

=== 詳解

Identity Equal或 Strict Equal, 在 ECMAScript -- Java Script 所遵守的標準中,算法的定義為:The Strict Equality Comparison Algorithm, 規則如下:

  1. 如果?參數 x 的數據類型和 參數 y 的數據類型不一致,這返回 false
  2. 如果 參數 x 的數據類型為 undenfined, 則返回 true
  3. 如果 參數 x 的數據類型為 null, 則返回 true
  4. 如果 參數 x 的數據類型為 Number, 則:
    1. 如果 x?是? NaN 返回 false
    2. 如果?y?是? NaN 返回 false
    3. 如果 x 是 +0 并且 y 為 -0, 返回 true
    4. 如果 x 是 -0 并且 y 為 +0, 返回 true
    5. 如果 x 和 y 有著相同的數值,返回 true
    6. 返回 false
  5. 如果 x 的類型為 String, 且 x 與 y 有著相同的順序排列的字符串, 返回 true
  6. 如果 x 的類型為 boolean, 且 x 與 y 擁有相同的布爾值,返回 true
  7. 如果 x 的類型為 Object, 且 x 與 y 指向相同的對象,返回 true

偽代碼:

 1 function strictEqual(x, y) {
 2     // If Type(x) is different from Type(y), return false.
 3     if (!valueEqual(typeof (x), typeof (y))) {
 4         return false;
 5     }
 6 
 7     // If Type(x) is Undefined, return true.
 8     // If Type(x) is Null, return true.
 9     if (valueEqual(typeof (x), "undefined") || valueEqual(x, null)) {
10         return true;
11     }
12 
13 
14     if (valueEqual(typeof (x), "number")) {
15         // If x is NaN, return false.
16         if (isNaN(x)) {
17             return false;
18         }
19 
20         // If y is NaN, return false.
21         if (isNaN(y)) {
22             return false;
23         }
24      
25         // If x is +0 and y is ?0, return true.
26         if (valueEqual(x, +0) && valueEqual(y, -0)) {
27             return true;
28         }
29 
30         // If x is ?0 and y is +0, return true.
31         if (valueEqual(y, +0) && valueEqual(x, -0)) {
32             return true;
33         }
34 
35         // If x is the same Number value as y, return true.
36         if (valueEqual(x, y)) {
37             return true;
38         }
39 
40         return false;
41     }
42 
43     if (valueEqual(typeof (x), "string")) {
44         // If Type(x) is String, then return true if x and y are exactly
45         // the same sequence of characters 
46         //   (same length and same characters in corresponding positions); otherwise, return false.
47         return hasSameChar(x, y);
48     }
49 
50     if (valueEqual(typeof (x), "boolean")) {
51         return valueEqual(x, y);
52     }
53 
54     if (valueEqual(typeof (x), "object")) {
55         // Return true if x and y refer to the same object. Otherwise, return false.
56         return hasSameReference(x, y);
57     }
58 
59     return false;
60 }
View Code

?

邏輯圖:

== 詳解

Equal, 在兩個對比變量數據類型相同時, 和=== 有著一樣的行為算法實現,但是當兩個對比的變量數據類型不同時,ECMAScript/JavaScript 有著自定義的轉換和比較邏輯:參考 The Abstract Equality Comparison Algorithm

  1. 如果 x 為 null, 且 y 為 undefined, 返回 true
  2. 如果 x 為 undefined, 且 y 為 null, 返回 true
  3. 如果 x 的數據類型為 Number, 且 y 的數據類型為 string, 則將 y 轉換為 Number,然后進行比較
  4. 如果 x 的數據類型為 String, 且 y 的數據類型為 Number, 則將?x 轉換為 Number,然后進行比較
  5. 如果 x 的數據類型為 Boolean,?將x 轉換為數字類型,當 x 為 true 時轉換為 1, 否則轉換為 0 進行比較
  6. 如果?y 的數據類型為 Boolean,?將 y?轉換為數字類型,當 y 為 true 時轉換為 1, 否則轉換為 0 進行比較
  7. 如果 x 的數據類型為 String 或者 Number, 且 y 為 Object, 則使用 valueOf 函數,將 y 轉換為簡單類型進行比較
  8. 如果?y 的數據類型為 String 或者 Number, 且?x 為 Object, 則使用 valueOf 函數,將?x 轉換為簡單類型進行比較
  9. 返回 false

   從上述定義不難總結出以下幾點:

    1. 該算法為遞歸算法,轉換后,繼續調用其自身直到能比較且返回為止
    2. 該算法依賴于 Strict Equal 的實現
    3. 進行轉換時,具體轉換依賴于數據類型的定義的方法,如Number() 函數

  偽代碼:

 1 function abstractEqual(x, y) {
 2 
 3     // if x and y has same type
 4     if (valueEqual(typeof (x), typeof (y))) {
 5         return strictEqual(x, y);
 6     }
 7 
 8     // If x is null and y is undefined, return true.
 9     if (valueEqual(x, null) && valueEqual(y, undefined)) {
10         return true;
11     }
12 
13     // If x is undefined and y is null, return true.
14     if (valueEqual(x, undefined) && valueEqual(y, null)) {
15         return true;
16     }
17 
18     // Type(x) is Number and Type(y) is String,
19     if (valueEqual(typeof (x), "number") && valueEqual(typeof (y), "string")) {
20 
21         var convertedY = Number(y);
22 
23         // return the result of the comparison x == ToNumber(y)
24         return abstractEqual(x, convertedY);
25     }
26 
27     // Type(x) is Number and Type(y) is String,
28     if (valueEqual(typeof (x), "string") && valueEqual(typeof (y), "number")) {
29 
30         var convertedX = Number(x);
31 
32         // return the result of the comparison x == ToNumber(y)
33         return abstractEqual(convertedX, y);
34     }
35 
36     // Type(x) is Boolean, return the result of the comparison ToNumber(x) == y.
37     if (valueEqual(typeof (x), "boolean")) {
38         var convertedToIntX = Number(x);
39 
40         return abstractEqual(convertedToIntX, y);
41     }
42 
43     // Type(x) is Boolean
44     if (valueEqual(typeof (y), "boolean")) {
45         var convertedToIntY = Number(y);
46 
47         // return the result of the comparison ToNumber(x) == y.
48         return abstractEqual(x, convertedToIntY);
49     }
50 
51     // If Type(x) is either String or Number and Type(y) is Object,
52     if ((valueEqual(typeof (x), "string") || valueEqual(typeof (x), "number")) && valueEqual(typeof (y), "object")) {
53         var toPrimitiveY = y.valueOf();
54 
55         // return the result of the comparison x == ToPrimitive(y).
56         return abstractEqual(x, toPrimitiveY);
57     }
58 
59 
60     // If Type(x) is either String or Number and Type(y) is Object,
61     if ((valueEqual(typeof (y), "string") || valueEqual(typeof (y), "number")) && valueEqual(typeof (x), "object")) {
62         var toPrimitiveX = x.valueOf();
63 
64         // return the result of the comparison x == ToPrimitive(y).
65         return abstractEqual(toPrimitiveX, y);
66     }
67 
68     return false;
69 }
View Code

?

?

邏輯圖:

?

?

附加上本例使用的判斷相等的函數的代碼,直接使用了 JavaScript 的 == 來實現,為了 demo 么!呵呵,這是一個很號的接口,實際上,我也實現不出來 :).

 1 function valueEqual(x, y) {
 2     return x === y;
 3 }
 4 
 5 function hasSameChar(x, y) {
 6     return x === y;
 7 }
 8 
 9 function hasSameReference(x, y) {
10     return x === y;
11 }
View Code

?

總結

現在,我們已經知道 == 和 === 在判斷兩個變量是否相等時所使用的算法的基本實現。幫助我們理解一些 JavaScript 中判斷相等時一些"詭異“ 的行為。

把我們寫的 Script 放在一個 HTML 文件里,用 Chrome 代開,按 F12, 開始我們的調試吧:

測試 JS 代碼運行結果 ???  ????JS 代碼  運行結果備注
var x = 1, y = "1";console.log(strictEqual(x,y)); console.log(abstractEqual(x,y))false, truevar x = 1, y = "1";console.log(x === y); console.log(x == y)false,true== 時,y 先轉換為數字類型1
var x = 1, y = "not a number";console.log(strictEqual(x,y)); console.log(abstractEqual(x,y))false, falasevar x = 1, y = "not a number";console.log(x === y); console.log(x == y)false, false?y 轉換為數字類型失敗,返回 NaN,NaN 不與任何值相等,包括 NaN 自身                  
var x = undefined, y = null;console.log(strictEqual(x,y)); console.log(abstractEqual(x,y))false,truevar x = undefined, y = null;console.log(x===y); console.log(x == y)

false,true

=== 時, null != undefined

== 時,規定了 null 與 undefined 的相等

var x = true, y = 2;console.log(strictEqual(x,y)); console.log(abstractEqual(x,y))false,falsevar x = true, y = 2;console.log(x === y); console.log(x == y)

?false,false

true 轉換為數字 1    

var x = false, y = 0;console.log(strictEqual(x,y)); console.log(abstractEqual(x,y))false,truevar x = false, y = 0;console.log(x === y); console.log(x == y)

false,true  

?false 轉換為數字 0

var x = {name:'test',valueOf:function(){return 1;}},y = 1; console.log(strictEqual(x,y));console.log(abstractEqual(x,y));false,truevar x = {name:'test',valueOf:function(){return 1;}},y = 1; console.log(x === y);console.log(x == y);

false,true

?x.valueOf()? 返回數字 1,與 y 相等

轉載于:https://www.cnblogs.com/xinghuayang/p/JS_Equal_VS_IdentityEqual.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/375040.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/375040.shtml
英文地址,請注明出處:http://en.pswp.cn/news/375040.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

靶場練習第十五天~vulnhub靶場之dc-7

一、準備工作 kali和靶機都選擇NAT模式(kali與靶機同網段) 1.靶場環境 下載鏈接:https://download.vulnhub.com/dc/DC-7.zip 2.kali的ip 命令:ifconfig 3.靶機的ip 掃描靶機ip sudo arp-scan -l 二、信息收集 1.nmap的信息收集 (1&…

ubuntu系統下如何修改host

Ubuntu系統的Hosts只需修改/etc/hosts文件,在目錄中還有一個hosts.conf文件,剛開始還以為只需要修改這個就可以了,結果發現是需要修改hosts。修改完之后要重啟網絡。具體過程如下:1、修改hostssudo gedit /etc/hosts2、添加解析記…

Matplotlib不顯示圖形

安裝好了Matplotlib,使用官方一個例子測試運行時,發現使用畫圖功能時,運行腳本老是顯示不出圖像,Google了一下,后來發現是matplotlibrc文件沒配置好。 參考了官方文檔,修改步驟如下 1.查找matplotlibrc文件…

靶場練習第十六天~vulnhub靶場之dc-8

一、準備工作 kali和靶機都選擇NAT模式(kali與靶機同網段) 1.靶場環境 下載鏈接:https://download.vulnhub.com/dc/DC-8.zip 2.kali的ip 命令:ifconfig 3.靶機的ip 掃描靶機ip sudo arp-scan -l 二、信息收集 1.nmap的信息收集 (1&…

【SpringMVC】SpringMVC系列4之@RequestParam 映射請求參數值

4、RequestParam 映射請求參數值 4.1、概述 Spring MVC 通過分析處理方法的簽名,將 HTTP 請求信息綁定到處理方法的相應人參中。Spring MVC 對控制器處理方法簽名的限制是很寬松的,幾乎可以按喜歡的任何方式對方法進行簽名。必要時可以對方法及方法入…

Sprint3

進展:今天主要是各自熟悉安卓應用開發平臺,設計了圖標,沒什么實際上的進展。 燃盡圖: 團隊工作照: 轉載于:https://www.cnblogs.com/XJXYJ/p/4495810.html

靶場練習第十七天~vulnhub靶場之dc-9

一、準備工作 kali和靶機都選擇NAT模式(kali與靶機同網段) 1.靶場環境 下載鏈接:https://download.vulnhub.com/dc/DC-9.zip 2.kali的ip 命令:ifconfig 3.靶機的ip 掃描靶機ip sudo arp-scan -l 二、信息收集 1.nmap的信息收集 (1&am…

Linux內核分析 02

二,操作系統是如何工作的 1、函數調用堆棧 三大法寶:存儲程序計算機 函數調用堆棧 中斷機制 堆棧:是C語言程序運行時必須的一個記錄調用路徑和參數的空間。是計算機內部現成的東西,我們直接使用。 包括函數調用框架、傳遞參數、保…

一 UI基本的用法

1. UIView的基本用法 //打印屏幕的寬和高CGRect screenBounds [[UIScreen mainScreen] bounds];NSLog("%f, %f", screenBounds.size.width, screenBounds.size.height);//創建一個UIView//UIView表示一個矩形區域UIView *v1 [[UIView alloc] init];//1.確定大小CGR…

靶場練習第十八天~vulnhub靶場之hackableII

一、準備工作 kali和靶機都選擇NAT模式(kali與靶機同網段) 1.靶場環境 下載鏈接:Hackable: II ~ VulnHub 2.kali的ip 命令:ifconfig 3.靶機的ip 掃描靶機ip sudo arp-scan -l 二、信息收集 1.nmap的信息收集 (1)掃描靶機開…

Object-c基礎(2)

類和對象 類 在Object-c中類,其接口(interface)和實現(implementation)是分離開來的 類的聲明 interface 類名:父類名{實例變量的定義;}方法聲明;...end類的實現 implementation 類名方法定義...end對象 一個類提供…

arm linux 下移植busybox 的tftp

(1)進入busybox目錄,make menuconfig ,然后在networking中勾選tftp項跟tftpd項。 (2)配置/etc/inetd.conf 中關于tftp的選項(此部未驗證,不需要應該也可以) tftp dgra…

靶場練習第二十天~vulnhub靶場之Funbox: Scriptkiddie

一、環境搭建 靶官網機下載地址:Funbox: Scriptkiddie ~ VulnHub 百度云盤下載鏈接: 百度網盤 請輸入提取碼 提取碼: i4a9 二、信息收集 1.nmap命令掃描靶機 先用ifconfig查看kali的IP,因為kali和靶機都是NAT模式下,所以用 nmap 192.168…

documentbodyscrollTop的值總為零的解決辦法

有一個功能需要判斷返回頂部按鈕是否顯示。 JS代碼如下: var sTop document.body.scrollTop;if(sTop>100){document.getElementById("sm_top").style.display"block";}else{document.getElementById("sm_top").style.display&quo…

spring mvc 多線程并發

ThreadLocal為解決多線程程序的并發問題提供了一種新的思路。使用這個工具類可以很簡潔地編寫出優美的多線程程序。 http://www.xuebuyuan.com/1628190.html 我們知道Spring通過各種DAO模板類降低了開發者使用各種數據持久技術的難度。這些模板類都是線程安全的,也就…

靶場練習第十九天~vulnhub靶場之GreenOptic: 1

一、準備工作 kali和靶機都選擇NAT模式(kali與靶機同網段) 1.靶場環境 下載鏈接:GreenOptic: 1 ~ VulnHub 2.kali的ip 命令:ifconfig 3.靶機的ip 掃描靶機ip sudo arp-scan -l 二、信息收集 1.nmap的信息收集 (1)掃描靶機開…

靶場練習第二十五天~vulnhub靶場之Raven-2

一、準備工作 kali和靶機都選擇NAT模式(kali與靶機同網段) 1.靶場環境 下載鏈接:Raven: 2 ~ VulnHub 2.kali的ip 命令:ifconfig 3.靶機的ip 掃描靶機ip sudo arp-scan -l 二、信息收集 1.nmap的信息收集 (1)掃描靶機開放的…

每天一個linux命令(46):vmstat命令

vmstat是Virtual Meomory Statistics(虛擬內存統計)的縮寫,可對操作系統的虛擬內存、進程、CPU活動進行監控。他是對系統的整體情況進行統計,不足之處是無法對某個進程進行深入分析。vmstat 工具提供了一種低開銷的系統性能觀察方…

用TypeScript開發了一個網頁游戲引擎,開放源代碼

最開始學習電腦編程的原動力之一就是想自己編寫游戲,一方面很好奇這些游戲是怎么做出來的,另一方面覺得有些地方設計的不合理,希望電腦游戲既能讓人玩的有趣,又不浪費時間。 學校五年,畢業十年,學用了十多種…

靶場練習第二十一天~vulnhub靶場之Momentum-1

一、環境搭建 1.ifconfig查看kali的ip 2.創建靶機 靶機下載地址:Momentum: 1 ~ VulnHub 二、信息收集 1.nmap命令 尋找靶機ip:nmap 192.168.101.0/24 2.端口掃描 使用命令:nmap -A -T4 -p 1-65535 192.168.101.113,發現開放2…