我们都去过那里…您使用==
比较了两个值,收到一个完全出乎意料的结果,而Wonder wt*正在进行?! - 只有equality ==
运算符。
equality ==
运算符具有以下语法。
x == y
需要两个操作数,x
和y
,将它们转换为相同的类型,按值进行比较并返回Boolean
结果。
始终使用严格的平等
===
操作员。实际上,使用==
而不是===
没有任何好处,除非您的目标是将错误引入您的代码库。
但是您没有来这里,所以我可以告诉您开始使用===
。只需查看下面的代码即可。您想知道如何解释它,不是吗? - 是的,您应该知道。您正在使用JavaScript,这是一个JavaScript功能 - 因此,拥抱它!
'' == '0' // Result: false
0 == '' // Result: true
0 == '0' // Result: true
false == undefined // Result: false
false == null // Result: false
null == undefined // Result: true
[] == 0 // Result: true
[] == '0' // Result: false
['a', 'b'] == 'a,b' // Result: true
NaN == NaN // Result: false
'\n\r\t' == 0 // Result: true
Isloosely equorithm
当您在引擎盖下使用==
时,该算法会启动并给出比较的结果。所以,是的,这是我们痛苦的方法。
该算法在ECMAScript specification中进行了描述,基本上每个JavaScript engine都必须按照所述实施。
通常用某种图表或流程图表示算法,但是由于我擅长绘画,所以我向您介绍了这个宏伟的pseudocode。
Take two operands, `x` and `y`, as an input
If type of `x` is the same as type of `y`
If type of `x` is `Undefined`
return `true`
If type of `x` is `Null`
return `true`
If type of `x` is `Number`
If `x` is `NaN`
return `false`
If `y` is `NaN`
return `false`
If `x` is the same as `y`
return `true`
If `x` is `-0` and `y` is `+0`
return `true`
if `x` is `+0` and `y` is `-0`
return `true`
return `false`
If the type of `x` is `String`
If `x` and `y` are exactly the same sequence of characters
return `true`
return `false`
If the type of `x` is `Boolean`
If `x` and `y` are both `true`
return `true`
If `x` and `y` are both `false`
return `true`
return `false`
If `x` and `y` refer to the same object
return `true`
return `false`
If `x` is `null` and `y` is `undefined`
return `true`
If `x` is `undefined` and `y` is `null`
return `true`.
If type of `x` is `Number` and type of `y` is `String`
Convert `y` to `Number`
Return the result of the comparison `x == y`
If type of `x` is `String` and type of `y` is `Number`
Convert `x` to `Number`
Return the result of the comparison `x == y`
If type of `x` is `Boolean`
Convert `x` to `Number`
Return the result of the comparison `x == y`
If type of `y` is `Boolean`
Convert `y` to `Number`
Return the result of the comparison `x == y`
If type of `x` is either `String` or `Number` and type of `y` is `Object`
Convert `y` to primitive value
Return the result of the comparison `x == y`
If type of `x` is `Object` and type of `y` is either `String` or `Number`
Convert `x` to primitive value
Return the result of the comparison `x == y`
Return `false`
请记住,算法的某些部分在伪代表中缺少。如果您想查看详细的规格,请在Ecmascript网站上查看。
是的,我知道,这只是一堆IF语句和转换。这个转换部分确实是重要的。您会看到,当类型相同时,==
的行为与===
运算符完全相同。重要的区别是,当类型不同时,==
会强制强制。
胁迫是一个花式的JavaScript术语,当我们谈论从一个值类型转换为另一种值,例如从字符串到数字。胁迫在==
比较中起重要作用。
如果您不想记住整个算法,请以这种方式考虑一下。如果操作数没有相同的类型,则将其转换为Number
。当类型相同时,按值比较操作数。
对原始的对象
在我们关注一些示例之前,更重要的是将Object
类型值转换为原始值。
在JavaScript中,有7个原始值: string , number , bigint , boolean ,未定义的, null 和符号。
Object
类型的值可以通过==
运算符自动将其转换为原始值。当一个操作数的类型为Object
时,另一个操作数具有原始类型之一。
将Object
转换为原始价值时,JavaScript将做几件事。它将首先尝试调用内置的原型方法valueOf
。如果valueOf
不返回原始值,则内置的原型方法toString
将被称为接下来。
正如JavaScript中几乎所有的行为一样,这种行为有几个边缘案例,可以修改和覆盖,但是您现在不必担心它。
例子
仍然记得从一开始就记得该代码样本了吗?现在,当我们知道algorithm works时
我将在这里做一个假设。 ==
左侧的操作数将称为x
,右侧的操作数将称为y
。从此开始,让我们开始。
请记住,如果操作数没有相同的类型,则==
将执行类型转换,只要操作数具有不同的类型。只有这样,才能按值比较操作数。
样本01
'' == '0'
// Result: false
这个非常简单。这两个操作数具有相同类型的String
。这意味着将按价值比较奥运会。由于值不相同,因此结果为false
。
样本02
0 == ''
// Result: true
操作数的类型x
是Number
,操作数的类型y
是String
。类型不一样,y
将转换为Number
。
空字符串''
转换为Number
,将为0
。通过在浏览器的控制台中运行Number('')
来测试它。
转换完成后,将按值比较操作数。由于值相同,因此0
确实等于0
,结果将为true
。
样本03
0 == '0' // Result: true
操作数的类型x
是Number
,而操作数y
的类型为String
。操作数y
将转换为Number
。
当'0'
转换为Number
时,其值将为0
。通过在浏览器的控制台中运行Number('0')
来测试它。
转换完成后,将按值比较操作数。由于值相同,因此0
确实等于0
,结果将为true
。
样本04
false == undefined // Result: false
false == null // Result: false
null == undefined // Result: true
我将这些示例分组在一起,因为这种行为的推理几乎是相同的。
根据算法,undefined
只能等于undefined
或null
。对于null
,它也只能等于null
或undefined
。因此,将它们与false
进行比较将始终导致false
。
样本05
[] == 0 // Result: true
操作数x
是Object
的类型,操作数y
的类型为String
。正如我们已经知道的那样,在可以通过价值比较它们之前,将发生类型转换。在这种情况下,操作数x
将转换为原始值。这意味着koude16 to primitive转换将开始。
因此,让我们看看[]
转换为原始价值的样子。方法valueOf
将直接在[]
上调用。通过在浏览器的控制台中运行[].valueOf()
来对其进行测试。此操作的结果将是[]
。
您可以看到,我们仍然有不是原始值的[]
,因此toString()
被调用。通过在浏览器的控制台中运行[].toString()
来测试它。返回的值是''
,它是原始值。这样,将Object
转换为原始价值。
但是,仔细看,操作数仍然具有不同的类型,x
现在是''
,它是String
类型,而y
仍然是0
,它是Number
类型。转换必须继续。
现在,x
将转换为Number
。从以前的示例中,我们已经知道''
将在转换后成为0
。转换完成后,将按值比较操作数。由于值相同,因此0
确实等于0
,结果将为true
。
样本06
[] == '0' // Result: false
操作数x
是Object
的类型,但是操作数y
是String
的类型。具有Value []
的操作数x
将转换为原始值。我们已经知道,从Sample 05中,此转换的结果将是空字符串''
。转换后,操作数x
将具有值为''
和type String
。
由于两个歌剧院现在都是相同类型的String
,因此已完成转换。当按值进行比较时,''
与'0'
不同,因此比较为false
。
样本07
['a', 'b'] == 'a,b' // Result: true
操作数x
是Object
的类型,操作数y
是String
的类型。在转换步骤中,Object
将转换为to primitive值。
转换后,操作数x
将具有值为'a,b'
和type String
。通过在浏览器的控制台中运行['a', 'b'].toString()
来测试它。
两个操作数现在都是String
的类型。当按值比较时,结果为true
,因为值相同。
样本08
NaN == NaN // Result: false
这个非常奇怪而又简单。将任何值与NaN
进行比较总是会导致false
。即使将NaN
与NaN
进行了比较,也很奇怪。
样本09
'\n\r\t' == 0 // Result: true
操作数具有不同的类型,因此需要转换。由于x
的类型为String
,它将转换为Number
。转换后,'\n\r\t'
将为0
。现在,当通过值比较时,0
与0
相同,因此结果是true
。
如果您想知道'\n\r\t'
在转换后如何变成0
-这是因为转换为Number
的工作方式。
有一些特殊的Single Character Escape Sequences,例如\n
(新线路),\t
(水平表),\v
(垂直标签),\r
(马车返回),当将转换为Number
时,它们始终将是0
。在同一字符串值中包含哪个顺序以及其中有多少个。
结论
我们都知道JavaScript可能很奇怪,但是如果您在引擎盖下看起来有些清晰,事情就会变得更加清晰。同样的事情是equality ==
运算符。从表面上看,这真的很奇怪,但是当您知道其背后的算法时,事情可能会变得容易得多。
无论哪种方式,我都强烈建议始终使用严格的equality ===
操作员。但是不要误会我的意思,知道==
的工作原理仍然非常重要。毕竟,这是一个始终是语言的JavaScript功能。
查看有关my blog的其他文章。