We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
作者:Dmitri Pavlutin 译者:前端小智 来源:dmitripavlutin
作者:Dmitri Pavlutin
译者:前端小智
来源:dmitripavlutin
阿里云最近在做活动,低至2折,有兴趣可以看看: https://promotion.aliyun.com/ntms/yunparter/invite.html?userCode=pxuujn3r
在日常的 JS 编码过程中,可能很难看到相等运算符(=)是如何工作的。特别是当操作数具有不同类型时。这有时会在条件语句中产生一些难以识别的 bug。很容易理解为什么 0 == 8 是 flase 的或者 '' == false 是 true。但是为什么{} == true是 false 的就看不出来了。接下将会讲这是肿么肥事。
=
0 == 8
flase
'' == false
true
{} == true
false
在这之前,先说几个术语:
操作符(Operator) 表示操作的符号。例如,相等运算符==比较两个值,三等运算符 === 比较两个值及其类型,加法运算符+两个数字和或连接两个字符串。
==
===
+
操作数(Operand) 是运算的主体,是执行运算的数量。例如,在表达式 0 == {} 中,0 是第一个操作数,{} 是第二个操作数。
0 == {}
0
{}
JS 中的基本数据类型(原始类型)有 number,string, boolean,null 和 undefined,symbol。
number
string
boolean
null
undefined
symbol
全等和不全等操作符遵循以下基本规则(IEA规则):
NaN
规则很简单。
值得一提的是,在全等运算中,NaN 与其他任何值相比,结果都是 false。 来看看考虑些例子,这是学习这些规则的好方式。
例 1
1 === "1" // false, 规则 1
操作数是不同的类型(数字和字符串),基于 IEA 规则1,它们是不等的。
例 2
0 === 0 // true, 规则 6
操作数具有相同的类型和相同的值,因此根据IEA规则6,它们是严格相等的。
例 3
undefined === undefined // true, 规则 3
两个操作数都是 undefined 的,应用 IEA 规则3,它们是相等的。
例 4
undefined === null // false, 规则 1
因为操作数是不同的类型,根据IEA规则1,它们并不相同。
例 5
NaN === NaN // false, IEA 规则 5
操作数是相同的类型,但是IEA 规则4 表明任何与 NaN 比较都是不相等的。
例 6
var firstObject = {}, secondObject = firstObject; secondObject['name'] = 'Neo'; secondObject === firstObject // true, IEA 规则 8
两个变量 firstObject 和 secondObject 都是对同一对象的引用,根据 IEA 规则8,它们相等。
firstObject
secondObject
例 7
[] === [] //false, IEA 规则 9
字面量 [] 创建了一个新的数组引用。这两个操作数是相同的类型(对象),但是它们引用不同的对象。根据 IEA 规则 9 ,它们不相等。
[]
对象到布尔值
对象到布尔值的转换非常简单:所有的对象(包括数字和函数)都转换为 true。对于包装对象亦是如此:new Boolean(false) 是一个对象而不是原始值,它将转换为 true。
new Boolean(false)
对象到字符串
对象到字符串 和 对象到数字 的转换都是通过调用待转换对象的一个方法来完成的。一个麻烦的事实是,JS 对象有两个不同的方法来执行转换,接下来要讨论的一些特殊场景更加复杂。值得注意的是,这里提到的字符串和对象的转换规则只适用于原生对象(native object)。宿主对象(例如有Web浏览器定义的对象)根据各自的算法可以转换成字符串和数字。
所有的对象继承了两个转换方法。第一个是toString(),它的作用是返回一个反映这个对象的字符串。默认的 toString() 方法并不会返回一个有趣的值:
toString()
({x:1,y:2}).toString() //=>"[object object]"
很多类定义了更多特定版本的toString()方法。例如,数组的 toString() 方法是将每个数组元素转换为一个字符串,并在元素之间添加逗号后合并成结果字符串。
函数的 toString() 方法返回了这个函数的实现定义。实际上,这里的实现是通常是将用户定义的函数转换为 JS 源代码字符串。
日期 Date 的 toString() 方法返回了一个可读的日期和时间字符串。
Date
RegExp 的 toString() 方法将RegExp对象转换为表示正则表达式直接量的字符串:
RegExp
来几个例子:
[1,2,3].toString() //=> "1,2,3" (function(x){ f(x); }).toString() // => "function(x){ f(x); }" /\d+/g.toString() // => "/\d+/g" new Date(2019,9,16).toString() //=> "Wed Oct 16 2019 00:00:00 GMT+0800 (中国标准时间)"
另一个转换对象的函数是 valueOf()。如果存在任意原始值,它就默认将对象转换为表示它的原始值。对象是复合值,而且大多数对象无法真正表示为一个原始值,因此默认的 valueOf() 方法简单地返回对象本身,而不是返回一个原始值。数组、函数和正则表达式简单地继承了这个方法,调用这些类型的实例的valueOf() 方法只是简单返回对象本身。日期 Date 的 valueOf() 方法会返回它的一个内部表示:1970年1月1日以来的毫秒数。
valueOf()
new Date(2019,9,16).valueOf() // 1571155200000
通过使用 toString() 和 valueOf() 方法,就可以做到对象到字符串和对象到数字的转换了。但需要注意的是,在某些特殊的场景中,JS 执行了完全不同的对象到原始值的转换。
JS 中对象到字符串的转换经过如下这些步骤,咱们简称 OPCA 算法。
如果方法 valueOf() 存在,则调用它。如果 valueOf() 返回一个原始值,JS 将这个值转换为字符串(如果本身不是字符串的话),并返回这个字符串结果。
如果方法 toString() 存在,则调用它。如果 toString() 返回一个原始值,JS 将这个值转换为字符串(如果本身不是字符串的话),并返回这个字符串结果。需要注意,原始值到字符串的转换。
否则,JS 无法从 toString() 或 valueOf() 获得一个原始值,它将抛出一个 TypeError:不能将对象转换为原始值 异常
TypeError:不能将对象转换为原始值
当调用 valueOf() 方法时,大多数原生对象都会返回对象本身。因此 toString() 方法使用得更频繁。
关于 Date 对象的注意事项:在转换为原始值时,对象立即使用 toString() 方法转换为字符串。这样,规则1就被跳过了。普通的 JS 对象,{}或 new object(),通常被转换成 "[object Object]"
new object()
"[object Object]"
数组通过将它的元素与“,”分隔符连接转换为。例如 [1,3,"four"] 被转换成" 1,3,four"。
“,”
[1,3,"four"]
" 1,3,four"
相等运算符 “==” 如果两个操作数不是同一类型,那么相等运算符会尝试一些类型转换,然后进行比较。
“==”
相等运算符算法(EEA)
1
1 == true // true
上面的转换步骤:
1 == true
1 == 1
1 === 1
'' == 0 // true
'' == 0
''
0 === 0
null == 0 // false
null == 0
null == undefined // true
null == undefined
NaN == NaN // false
NaN == NaN
NaN === NaN
[''] == '' // true
[''] == ''
['']
OPCA规则2
'' == ''
'' === ''
{} == true // false
{} == 1
“[object object]”== 1
“[object object]”
NaN == 1
NaN === 1
即使在详细研究了本文中的所有示例、学习了算法之后,你会发现要立即理解复杂的比较还需要时间的积累。
告诉你一些技巧。 将本文添加到书签中(使用Ctrl + D),下一次看到有趣的情况时,可以根据等式算法编写逐步的计算。 如果检查至少 10 个示例,则以后不会有任何问题。
10
现在就可以试试,如 [0] == 0 的结果和转化步骤是什么?
[0] == 0
相等运算符==进行类型转换。因此,可能会产生意想不到的结果,例如 {}== true 是 false( 参见例7)。在大多数情况下,使用全等操作符 === 更安全。
{}== true
相等和全等运算符号可能是最常用的运算符之一。理解它们是编写稳定且bug较少的 JS 的步骤之一。
代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug。
原文:https://dmitripavlutin.com/the-legend-of-javascript-equality-operator/
阿里云最近在做活动,低至2折,有兴趣可以看看:https://promotion.aliyun.com/ntms/yunparter/invite.html?userCode=pxuujn3r
干货系列文章汇总如下,觉得不错点个Star,欢迎 加群 互相学习。
https://github.com/qq449245884/xiaozhi
因为篇幅的限制,今天的分享只到这里。如果大家想了解更多的内容的话,可以去扫一扫每篇文章最下面的二维码,然后关注咱们的微信公众号,了解更多的资讯和有价值的内容。
每次整理文章,一般都到2点才睡觉,一周4次左右,挺苦的,还望支持,给点鼓励
The text was updated successfully, but these errors were encountered:
No branches or pull requests
阿里云最近在做活动,低至2折,有兴趣可以看看:
https://promotion.aliyun.com/ntms/yunparter/invite.html?userCode=pxuujn3r
在日常的 JS 编码过程中,可能很难看到相等运算符(
=
)是如何工作的。特别是当操作数具有不同类型时。这有时会在条件语句中产生一些难以识别的 bug。很容易理解为什么0 == 8
是flase
的或者'' == false
是true
。但是为什么{} == true
是false
的就看不出来了。接下将会讲这是肿么肥事。在这之前,先说几个术语:
操作符(Operator) 表示操作的符号。例如,相等运算符
==
比较两个值,三等运算符===
比较两个值及其类型,加法运算符+
两个数字和或连接两个字符串。操作数(Operand) 是运算的主体,是执行运算的数量。例如,在表达式
0 == {}
中,0
是第一个操作数,{}
是第二个操作数。JS 中的基本数据类型(原始类型)有
number
,string
,boolean
,null
和undefined
,symbol
。全等运算符 ===
全等和不全等操作符遵循以下基本规则(IEA规则):
null
,则它们是严格相等的undefined
,它们是严格相等的NaN
,它们就不是严格相等的true
或都为false
,它们是严格相等的number
类型并且具有相同的值,则它们是严格相等的string
类型并且具有相同的值,则它们是严格相等的规则很简单。
值得一提的是,在全等运算中,
NaN
与其他任何值相比,结果都是false
。 来看看考虑些例子,这是学习这些规则的好方式。例 1
操作数是不同的类型(数字和字符串),基于 IEA 规则1,它们是不等的。
例 2
操作数具有相同的类型和相同的值,因此根据IEA规则6,它们是严格相等的。
例 3
两个操作数都是
undefined
的,应用 IEA 规则3,它们是相等的。例 4
因为操作数是不同的类型,根据IEA规则1,它们并不相同。
例 5
操作数是相同的类型,但是IEA 规则4 表明任何与 NaN 比较都是不相等的。
例 6
两个变量
firstObject
和secondObject
都是对同一对象的引用,根据 IEA 规则8,它们相等。例 7
字面量
[]
创建了一个新的数组引用。这两个操作数是相同的类型(对象),但是它们引用不同的对象。根据 IEA 规则 9 ,它们不相等。对象转换为原始值的规则
对象到布尔值
对象到布尔值的转换非常简单:所有的对象(包括数字和函数)都转换为
true
。对于包装对象亦是如此:new Boolean(false)
是一个对象而不是原始值,它将转换为true
。对象到字符串
对象到字符串 和 对象到数字 的转换都是通过调用待转换对象的一个方法来完成的。一个麻烦的事实是,JS 对象有两个不同的方法来执行转换,接下来要讨论的一些特殊场景更加复杂。值得注意的是,这里提到的字符串和对象的转换规则只适用于原生对象(native object)。宿主对象(例如有Web浏览器定义的对象)根据各自的算法可以转换成字符串和数字。
所有的对象继承了两个转换方法。第一个是
toString()
,它的作用是返回一个反映这个对象的字符串。默认的toString()
方法并不会返回一个有趣的值:很多类定义了更多特定版本的
toString()
方法。例如,数组的toString()
方法是将每个数组元素转换为一个字符串,并在元素之间添加逗号后合并成结果字符串。函数的
toString()
方法返回了这个函数的实现定义。实际上,这里的实现是通常是将用户定义的函数转换为 JS 源代码字符串。日期
Date
的toString()
方法返回了一个可读的日期和时间字符串。RegExp
的toString()
方法将RegExp对象转换为表示正则表达式直接量的字符串:来几个例子:
另一个转换对象的函数是
valueOf()
。如果存在任意原始值,它就默认将对象转换为表示它的原始值。对象是复合值,而且大多数对象无法真正表示为一个原始值,因此默认的valueOf()
方法简单地返回对象本身,而不是返回一个原始值。数组、函数和正则表达式简单地继承了这个方法,调用这些类型的实例的valueOf()
方法只是简单返回对象本身。日期Date
的valueOf()
方法会返回它的一个内部表示:1970年1月1日以来的毫秒数。通过使用
toString()
和valueOf()
方法,就可以做到对象到字符串和对象到数字的转换了。但需要注意的是,在某些特殊的场景中,JS 执行了完全不同的对象到原始值的转换。JS 中对象到字符串的转换经过如下这些步骤,咱们简称 OPCA 算法。
如果方法
valueOf()
存在,则调用它。如果valueOf()
返回一个原始值,JS 将这个值转换为字符串(如果本身不是字符串的话),并返回这个字符串结果。如果方法
toString()
存在,则调用它。如果toString()
返回一个原始值,JS 将这个值转换为字符串(如果本身不是字符串的话),并返回这个字符串结果。需要注意,原始值到字符串的转换。否则,JS 无法从
toString()
或valueOf()
获得一个原始值,它将抛出一个TypeError:不能将对象转换为原始值
异常当调用
valueOf()
方法时,大多数原生对象都会返回对象本身。因此toString()
方法使用得更频繁。关于
Date
对象的注意事项:在转换为原始值时,对象立即使用toString()
方法转换为字符串。这样,规则1就被跳过了。普通的 JS 对象,{}
或new object()
,通常被转换成"[object Object]"
数组通过将它的元素与
“,”
分隔符连接转换为。例如[1,3,"four"]
被转换成" 1,3,four"
。相等运算符 ==
相等运算符
“==”
如果两个操作数不是同一类型,那么相等运算符会尝试一些类型转换,然后进行比较。相等运算符算法(EEA)
2.1如果一个操作数为
null
而另一个undefined
,则它们相等2.2如果一个值是数字,另一个是字符串,先将字符串转换为数字,然后使用转换后的值比较
2.3如果一个操作数是布尔值,则将
true
转换为1
,将false
转换为0
,然后使用转换后的值比较2.4如果一个操作数是一个对象,而另一个操作数是一个数字或字符串,则使用OPCA将该对象转换为原原始值,再使用转换后的值比较
例 1
上面的转换步骤:
1 == true
(使用EEA 规则2.3 将true
转换为1
)1 == 1
(操作数有相同的类型。使用 EEA 规则1 将相等转换为全等运算进行比较1 === 1
(两个操作数都是数字,并且具有相同的值。根据 IEA 规则 6,这是相等的)true
例 2
上面的转换步骤:
'' == 0
(一个操作数是字符串,另一个操作数是数字,根据EEA规则2.2,''
被转换为数字0
)0 === 0
(操作数类型相同,值相同,所以根据IEA规则6,它是一个恒等式)true
例 3
上面的转换步骤:
null == 0
(null
是原始类型,0 是number
类型。根据EEA规则3)false
例 4
上面的转换步骤:
null == undefined
(基于EEA规则2.1,操作数相等)true
例 5
上面的转换步骤:
NaN == NaN
(两个操作数都是数字。根据EEA规则1,将相等转换为全等运算进行比较)NaN === NaN
(根据IEA规则4,操作数严格不相等)false
例 6
上面的转换步骤:
[''] == ''
(['']
是一个数组和''
是一个字符串。应用EEA规则2.4并使用OPCA规则2
将数组转换为原始值''
)'' == ''
(两个操作数都是字符串,将相等转换为全等运算进行比较)'' === ''
(两个操作数类型相同,值相同。使用IEA规则7,它们是相等的)true
例 7
上面的转换步骤:
{} == true
(使用EEA规则2.3,将true
操作数转换为1
){} == 1
(第一个操作数是一个对象,因此有必要使用OPCA将其转换为原始值)“[object object]”== 1
(因为第一个操作数是字符串,第二个操作数是数字,根据 EEA规则2.2 将“[object object]”
转换为数字)NaN == 1
(两个操作数都是数字,因此使用 EEA规则1 将相等转换为全等运算进行比较)NaN === 1
(根据 IEA规则4,没有什么是与NaN
相等的,结果是false
)false
实用技巧
即使在详细研究了本文中的所有示例、学习了算法之后,你会发现要立即理解复杂的比较还需要时间的积累。
告诉你一些技巧。 将本文添加到书签中(使用Ctrl + D),下一次看到有趣的情况时,可以根据等式算法编写逐步的计算。 如果检查至少
10
个示例,则以后不会有任何问题。现在就可以试试,如
[0] == 0
的结果和转化步骤是什么?相等运算符
==
进行类型转换。因此,可能会产生意想不到的结果,例如{}== true
是false
( 参见例7)。在大多数情况下,使用全等操作符===
更安全。总结
相等和全等运算符号可能是最常用的运算符之一。理解它们是编写稳定且bug较少的 JS 的步骤之一。
代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug。
原文:https://dmitripavlutin.com/the-legend-of-javascript-equality-operator/
交流
阿里云最近在做活动,低至2折,有兴趣可以看看:https://promotion.aliyun.com/ntms/yunparter/invite.html?userCode=pxuujn3r
干货系列文章汇总如下,觉得不错点个Star,欢迎 加群 互相学习。
因为篇幅的限制,今天的分享只到这里。如果大家想了解更多的内容的话,可以去扫一扫每篇文章最下面的二维码,然后关注咱们的微信公众号,了解更多的资讯和有价值的内容。
每次整理文章,一般都到2点才睡觉,一周4次左右,挺苦的,还望支持,给点鼓励
The text was updated successfully, but these errors were encountered: