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.mzph.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&…

靶场练习第十六天~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语言程序运行时必须的一个记录调用路径和参数的空间。是计算机内部现成的东西,我们直接使用。 包括函数调用框架、传递参数、保…

靶场练习第十八天~vulnhub靶场之hackableII

一、准备工作 kali和靶机都选择NAT模式(kali与靶机同网段) 1.靶场环境 下载链接:Hackable: II ~ VulnHub 2.kali的ip 命令:ifconfig 3.靶机的ip 扫描靶机ip sudo arp-scan -l 二、信息收集 1.nmap的信息收集 (1)扫描靶机开…

靶场练习第二十天~vulnhub靶场之Funbox: Scriptkiddie

一、环境搭建 靶官网机下载地址:Funbox: Scriptkiddie ~ VulnHub 百度云盘下载链接: 百度网盘 请输入提取码 提取码: i4a9 二、信息收集 1.nmap命令扫描靶机 先用ifconfig查看kali的IP,因为kali和靶机都是NAT模式下,所以用 nmap 192.168…

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…

靶场练习第二十二天~vulnhub靶场之Momentum-2

一、准备工作 靶机下载地址:Momentum: 2 ~ VulnHub 1.查看kali的ip 使用命令ifconfig 2.使用nmap命令 nmap 192.168.101.0/24 查看开放的端口和协议:nmap -sV 192.168.101.114 二、信息收集 1.使用gobuster,寻找隐藏的网站 gobuster di…

索引深入浅出(8/10):覆盖索引或列包含

在索引深入浅出:非聚集索引的B树结构在聚集表里,在聚集表里,我们看到非聚集索引的叶子层只包含非聚集索引键和聚集索引键。从聚集表结构或堆表结构里拿到剩下列,SQL Server需要进行书签/键查找操作。很多情况下书签或键查找非常消…

靶场练习第二十三天~vulnhub靶场之GOATSELINUX: 1

一、准备工作 kali和靶机都选择NAT模式(kali与靶机同网段) 1.靶场环境 下载链接:GoatseLinux: 1 ~ VulnHub 2.kali的ip 命令:ifconfig 3.靶机的ip 扫描靶机ip sudo arp-scan -l 二、信息收集 1.nmap的信息收集 (1)扫描靶机…

靶场练习第二十四天~vulnhub靶场之Raven-1

一、准备工作 kali和靶机都选择NAT模式(kali与靶机同网段) 1.靶场环境 下载链接:Raven: 1 ~ VulnHub 2.kali的ip 命令:ifconfig 3.靶机的ip 扫描靶机ip sudo arp-scan -l 二、信息收集 1.nmap的信息收集 (1)扫描靶机开放的…

【知识积累】DES算法之C#加密Java解密

一、前言 在项目需要添加安全模块,客户端调用服务端发布的service必须要经过验证,加密算法采用DES,客户端采用C#进行加密,服务端使用Java进行解密。废话不多说,直接上代码。 二、客户端 客户端采用C#进行开发&#xff…

Space.js – HTML 驱动的页面 3D 滚动效果

为了让我们的信息能够有效地沟通,我们需要创建用户和我们的媒体之间的强有力的联系。今天我们就来探讨在网络上呈现故事的新方法,并为此创造了一个开源和免费使用的 JavaScript 库称为 space.js。该库是 HTML 驱动的,这意味着你不需要在网站上…