资讯专栏INFORMATION COLUMN

你真的理解==和===的区别吗?

TwIStOy / 573人阅读

摘要:上面的理解是错的,和返回就可以推翻。解释不清楚和是相等的。和的规则类似,唯一少了转换的一步。三高级阶段参考规范真正理解真的如高设所说的那样吗其实不然。来分析一个经典的例子,看完彻底理解的强制转换。

用中文怎么叫合适?
相等?全等?
其实并不合适,叫double equals 或者treble equals,或者叫不懂的人觉得比较不专业的双等或者三等操作符,是更加严谨和正确的叫法。
为什么这么说?看完这篇博客你就明白了。

一、入门阶段:自我经验(一脚一坑)

我的理解是:
==是相等,值相等,返回true。
===是全等,值相等,类型也相等,返回true。

上面的理解是错的,[]==false[1]===[1]返回就可以推翻。[]==false,他们的值并不相等,但是返回true。[1]和[1],值相等,类型也相等,返回为false。因此上面理解是错的。

正确的理解是:

**==是相等,先转换再比较,返回true。
===是全等,不转换就比较,返回true。**

[]==false,false是转换为0,[]强制转换成0(解释不清楚),0 == 0 ,返回为true。
[1] === [1],不转换就比较,[1]===[1],左右的[1]指向内存中两个独立的,地址不同的数组,故返回false。

看下最简单的例子:
①基础类型vs基础类型
1== true //true
1 === true //false
再看两个复杂的例子:
②对象vs基础类型*
[] == false //true
[] === false //false
③对象vs对象
{age:6} == {age:6} //false
{age:6} === {age:6} //false
[1] == [1] //false
[1] === [1] //false

二、初级阶段:参考书籍(勉强避雷)

聪明的你会问了,[] == falsefalse == []的结果一致吗?
答案是一致的,因为无论再操作符左侧还是右侧,它们都是操作数,位置是没有关系的。

为什么会出现上面的结果?

为什么 1 == true[] == false返回true?
因为type coercion的存在,高设翻译为强制转型。
为什么会出现强制转换类型?
强制转换了谁的类型?
转换成了什么类型?

为什么{age:6} == {age:6}返回的是false?
他们看起来不是一样的吗,都是一个object,而且内部数据都是age:6,key-value值一模一样,为什么不返回true呢?

如果再在操作数中加入nullundefined这两个神奇的类型呢?
问题就变的更复杂了...

来看下《Javascript高级程序设计》关于==和===的规则

1.如果有一个操作数是布尔值,则在比较前先将其转换为数值,true转换为1,false转换为0,例如false == 0,true == 1
2.如果一个操作数是字符串,另一个操作数是数值,先将字符串转换成数值,例如"1"==1,"" ==0
3.如果一个操作数是对象,另一个操作数不是,则调用对象的valueOf()方法,用得到的基本类型按照前面的规则进行比较。(解释不清楚)
4.null和undefined是相等的。
5.如果有一个数是NaN,则相等操作符返回false,而不想等操作符返回true。NaN == NaN返回为false,因为规则如此。
6.如果两个操作数是对象,则比较它们是不是同一个对象。如果两个操作数都指向同一个对象,则相等操作符返回true,否则返回false。

例如:var obj = {a:1};foo = obj;bar = obj;foo==bar;foo==bar返回为true,因为他们指向同一个对象,obj。

===和==的规则类似,唯一少了转换的一步。
第6步中的foo===bar返回true,如果不明白为什么?请看第三部分。

三、高级阶段:参考规范(真正理解)

真的如高设所说的那样吗?其实不然。
下面是ecma-262的规范,其中有对==和===的执行定义,把解释不清楚干掉。
https://www.ecma-internationa...
7.2.13 Abstract Equality Comparison

The comparison x == y, where x and y are values, produces true or false. Such a comparison is performed
as follows:
1. If Type(x) is the same as Type(y), then
a. Return the result of performing Strict Equality Comparison x === y.
2. If x is null and y is undefined, return true.
3. If x is undefined and y is null, return true.
4. If Type(x) is Number and Type(y) is String, return the result of the comparison x == ToNumber(y).
5. If Type(x) is String and Type(y) is Number, return the result of the comparison ToNumber(x) == y.
6. If Type(x) is Boolean, return the result of the comparison ToNumber(x) == y.
7. If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
8. If Type(x) is either String, Number, or Symbol and Type(y) is Object, return the result of the
comparison x == ToPrimitive(y).
9. If Type(x) is Object and Type(y) is either String, Number, or Symbol, return the result of the
comparison ToPrimitive(x) == y.
10. Return false.

7.2.14 Strict Equality Comparison

The comparison x === y, where x and y are values, produces true or false. Such a comparison is performed
as follows:
1. If Type(x) is different from Type(y), return false.
2. If Type(x) is Number, then
a. If x is NaN, return false.
b. If y is NaN, return false.
c. If x is the same Number value as y, return true.
d. If x is +0 and y is ‑0, return true.
e. If x is ‑0 and y is +0, return true.
f. Return false.
3. Return SameValueNonNumber(x, y).
NOTE This algorithm differs from the SameValue Algorithm in its treatment of signed zeroes and
NaNs.

1.[]==false
来分析一个经典的例子:[]==false,看完彻底理解==的强制转换。
①[]==false→[]==0

7.If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).


经过ToNumber(false),false会被转换为0.
②[]==0→""==0

9.If Type(x) is Object and Type(y) is either String, Number, or Symbol, return the result of the
comparison ToPrimitive(x) == y

这个时候就比较复杂了...

按照规范,我们需要经过下面的一系列操作

→OrdinaryToPromitive([],default)
→OrdinaryToPromitive([],number)
→Get([],valueOf)
→Call(valueOf,[])
→Get([],toString)
→Call(toString,[])
→""

不要慌,用Javascript来描述,还是很简单的:

[].valueOf().toString()

③""==0→0==0

If Type(x) is String and Type(y) is Number, return the result of the comparison ToNumber(x) == y.

2.[1]===[1]
再来看下===操作符,其中有句话可以完美解释[1]===[1]返回false,但是var obj = {a:1};foo = obj;bar = obj;foo===bar中foo===bar返回为true的原因。

Return SameValueNonNumber(x, y).

由于[1]===[1]三等号左右的[1],不是same Object,因此返回为false.
而foo===bar,三等号左右其实本质上都是指向obj这个对象,值相等更是必然,所以返回为true。

我们由此可以举一反三,[1]==true返回true,而[1,2,3]==true返回false的原因也不足为奇了。

如有错误欢迎指正说明,期待和你交流~
努力成为优秀的前端工程师~

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/89210.html

相关文章

  • 理解机器学习中偏差 - 方差之间权衡

    摘要:机器学习中的偏差方差之间的权衡机器学习全部是关于给定输入数据和给定输出数据,然后去寻找一个最佳映射函数,这个映射函数通常也被叫做目标函数。 作者:chen_h微信号 & QQ:862251340微信公众号:coderpai简书地址:http://www.jianshu.com/p/f143... 我认为对偏差 - 方差之间的权衡判读对学习机器学习是非常重要的。那么为什么这么说呢?因为...

    lastSeries 评论0 收藏0
  • 理解=====

    摘要:开门见题说出以下几个表达式的结果张三张三补充知识要想回答上述问题,必须理解在执行时候的一些数据转换规则和成文的规定。根据上面第二条,写的明明白白,结果是。。根据,由于和指向不同引用,所以返回。 开门见题 说出以下几个表达式的结果 var obj1 = { name: 张三} var obj2 = obj1 var obj3 = { name: 张三} null == undefine...

    Barrior 评论0 收藏0
  • 2019前端工程师自检清单与思考

    摘要:前端工程师自检清单对于,掌握其语法和特性是最基本的,但是这些只是应用能力,最终仍旧考量仍然是计算机体系的理论知识,所以数据结构,算法,软件工程,设计模式等基础知识对前端工程师同样重要,这些知识的理解程度,可以决定你在前端工程师这条路上能走多 2019前端工程师自检清单 对于JavaScript,掌握其语法和特性是最基本的,但是这些只是应用能力,最终仍旧考量仍然是计算机体系的理论知识,所...

    Honwhy 评论0 收藏0
  • 容器容器镜像区别,您了解

    摘要:我们首先来看容器和容器镜像。容器和容器镜像一样,也是若干层的叠加,唯一区别是所有只读层的最上面一层,是一层可读可写层,如上图绿色图例所示。希望这篇文章能帮助大家理解容器和容器镜像的区别。 很多刚刚接触容器技术的朋友,不容易弄清楚容器,容器镜像和Docker这几个词的区别和联系。 showImg(https://segmentfault.com/img/remote/1460000017...

    zengdongbao 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<