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 }

逻辑图:

== 详解

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 }

逻辑图:

附加上本例使用的判断相等的函数的代码,直接使用了 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 }

总结

现在,我们已经知道 == 和 === 在判断两个变量是否相等时所使用的算法的基本实现。帮助我们理解一些 JavaScript 中判断相等时一些"诡异“ 的行为。

把我们写的 Script 放在一个 HTML 文件里,用 Chrome 代开,按 F12, 开始我们的调试吧:

测试 JS 代码 运行结果           JS 代码   运行结果 备注
var x = 1, y = "1";console.log(strictEqual(x,y)); console.log(abstractEqual(x,y)) false, true var 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, falase var 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,true var 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,false var 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,true var 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,true var x = {name:‘test‘,valueOf:function(){return 1;}},y = 1; console.log(x === y);console.log(x == y);
false,true


x.valueOf()  返回数字 1,与 y 相等

时间: 2024-10-11 15:42:30

Java Script 中 ==(Equal) 和 === (Identity Equal) 的区别和比较算法逻辑的相关文章

Java script 中的面向对象1

Java script 中的面向对象 对象 对象是Javascript的基本数据类型,对象是一种复合值,将很多的键值对聚合在一起使用.对象可看做是属性的无序集合,每个属性都是一个名/值对.属性名其实是一个字符串.我们可以把对象看做是字符串到值的映射. 创建对象 例子代码如下: <script type="text/javascript" language="JavaScript"> ????//创建一个对象o 有两个属性 x y ????????var

Java线程中run和start方法的区别

http://bbs.csdn.net/topics/350206340 Thread类中run()和start()方法的区别如下:run()方法:在本线程内调用该Runnable对象的run()方法,可以重复多次调用:start()方法:启动一个线程,调用该Runnable对象的run()方法,不能多次启动一个线程: package com.ljq.test; public class ThreadTest { /** * 观察直接调用run()和用start()启动一个线程的差别 * * @

java Script 中的keyCode 和charCode

其实很长一段时间,我都没有完全弄明白keyCode 和charCode ,自己也认真看过,但是就是理解不透彻,为了防止以后再出现混乱,写篇博客记录一下吧! 首先  在不同的浏览器中,他们有不同的说法哦. IE   keyCode  IE浏览器中event对象的属性(方法), 类型:Integer      可读写 描述:对于keypress事件,指示按下的键的Unicode字符;对于keyup\keydown 事件,指示按下的键盘是数字表示键. /*获取键盘的keycode 值*/       

Java Script中的Node

nodeType属性共有12种可取值,其中仅有3种具有实用价值. Element元素节点的nodeType属性值是1. attr属性节点的nodeType属性值是2. text文本节点的nodeType属性值是3. 使用nodeType属性可对指定的节点类型进行操作. Element继承了Node类,也就是说Element是Node多种类型中的一种,即当NodeType为1时Node即为ElementNode,另外Element扩展了Node,Element拥有id.class.children

Java -- Thread中start和run方法的区别

一.认识Thread的 start() 和 run() 1.start(): 我们先来看看API中对于该方法的介绍: 使该线程开始执行:Java 虚拟机调用该线程的 run 方法. 结果是两个线程并发地运行:当前线程(从调用返回给 start 方法)和另一个线程(执行其 run 方法). 多次启动一个线程是非法的.特别是当线程已经结束执行后,不能再重新启动. 用start方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码.通过调用Thread类的

在Java web中相对路径和绝对路径区别及应用方法(三)

(续) 三.解决方案 1.针对“现象一”的解决方案 在/OutSourcingManage/WebContent/WEB-INF/dispatcherServlet-servlet.xml文件中加入如下语句: <mvc:default-servlet-handler/> 2.针对“现象二”的解决方案 方法一.在/OutSourcingManage/WebContent/WEB-INF/dispatcherServlet-servlet.xml文件中加入如下语句: <mvc:resourc

Java线程中yield与join方法的区别

摘要:有人推崇产品,有人推崇运营,也有人推崇战略-到底该推崇什么?李智勇系统地分析了这三者之间的思路,并引用黑格尔的一句话,给出了自己的看法:在尺度中已经蕴含本质,这在产品.运营.战略的侧重上体现的非常好. 视野不拉升或者认知不深入时,就容易在盲人摸象层面上反复,看到微信火了,那就产品最重要,看到阿里火了,那就平台最重要.实际上一个比较显然的事实是,没有锥子一样的产品,那你就火不起来:不能从产品升级为平台,那就很可能活不下去.当然,有些人会说平台也是一种产品,但就和人与猴子都是灵长目,实际上仍是

在Java web中相对路径和绝对路径区别及应用方法(一)

闲来无事,研究了一下bootstrap框架,并把这个框架融入到我开发的一个项目中,在应用过程中发现了一些问题,经过潜心研究这个问题终于解决了,下面我就把整个过程分享给大家. 一.开发环境介绍 开发语言 JDK1.8 IDE ECLIPSE platform 4.6.0 WEB容器 tomcat9 后端框架 Spring+Spring MVC+Spring Data 前端框架 bootstrap3.3.7

Java泛型中&lt;T&gt; T 与 T的区别和用法

<T> T表示返回值是一个泛型,传递啥,就返回啥类型的数据,而单独的T就是表示限制你传递的参数类型,这个案例中,通过一个泛型的返回方式,获取每一个集合中的第一个数据, 通过返回值<T> T 和T的两种方法实现 一.<T> T 用法 二.T用法 原文地址:https://blog.51cto.com/3573186/2424310