当一个是布尔值时,为什么JavaScript将原始值转换为==运算符比较中的数字的原理?

前端之家收集整理的这篇文章主要介绍了当一个是布尔值时,为什么JavaScript将原始值转换为==运算符比较中的数字的原理?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我知道规则:

If the two operands are not of the same type,JavaScript converts the operands then applies strict comparison. If either operand is a number or a boolean,the operands are converted to numbers if possible; else if either operand is a string,the other operand is converted to a string if possible.

因此,如果(“true”)通过,但if(“true”== true)失败,因为它是if(NaN == 1)的句柄.

当一个值为布尔值时,我想知道这背后的理性是什么.在其他弱类型语言(如PHP)中,处理方式不同 – 如果一个值是布尔值,另一个值将转换为布尔值进行比较(而不是像javascript那样将数字转换为数字).

我假设这个选择是在仔细考虑的情况下为==运算符做出的.任何人都可以提供理由,为什么这是选择的功能?是否有一个常见的用例,这是选择解决?我打赌不仅仅是一个错误.

解决方法

来自es-discuss@mozilla.org邮件列表的Brendan Eich的响应速度非常快:

考虑Perl:

$perl -e 'print 0 == "true";'
1

好的,理由很差 – 但我在1995年5月,在AWK,Perl 4,Python 1.2(IIRC),TCL的阴影下创建了JS.

鉴于,我应该更多地关注AWK而不是Perl

$awk 'END {print(0 == "0")}'
1D
$awk 'END {print(0 == "")}'
0D

在某些方面,JS的==运算符通过转换为NaN来区分Perl(其中非数字字符串,如“true”转换为0)和AWK(其中只有“0”转换为0)之间的差异.这样,至少,我们有

js> 0 == ""
true
js> 0 == "true"
false

但完全的事实不是我在小心翼翼地模仿其他语言.相反,一些Netscapers努力将JS(然后是“Mocha”)嵌入到类似PHP的服务器(LiveWire)中,需要进行简单的转换,因此程序员可以匹配HTTP头字符串(服务器端)或HTML表单字段(客户端),例如,404等等,没有程序员的明确强制.

但这是90年代,我匆匆忙忙,这些前Borland Netscapers坚持不懈.所以,正如我在Strange Loop last year所说,“我是个白痴!我给了他们想要的东西!”

隐藏的转换是我在JS匆忙设计中最大的遗憾,没有.甚至包括’带’!

Does anyone know the exact reason the choice was made not to convert to boolean any value compared against a boolean in with the == operator?

一般的想法是狭窄的类型应该扩大.因此,true == 1通过将布尔{false,true}投影到{0,1}上,如在C中那样.

但是为什么不将true扩展为字符串,因为你的例子中的另一个操作数是“真的”?好问题.如果操作数是数字或布尔值,则将字符串作为数字进行比较的偏见源于HTTP标头和数字字符串HTML表单字段用例.不是很好的理由,但这就是JS“工作”的方式: – |.

您可以在ECMA-262 Edition 5.1规范,11.9.3抽象等效比较算法,步骤6& 7(根据步骤4和5阅读):

4.如果Type(x)为Number且Type(y)为String,则返回比较结果x == ToNumber(y).
5.如果Type(x)是String而Type(y)是Number,则返回比较结果ToNumber(x)== y.
6.如果Type(x)是布尔值,则返回比较结果ToNumber(x)== y.
7.如果Type(y)是布尔值,则返回比较结果x == ToNumber(y).

这是一个很大的“else”子句,其中x == y的Type(x)和Type(y)不相同.

对不起,这里没有明珠(原文如此).除了隐式转换之外,==和!=不会将操作数直接扩展(无中间转换)到最窄的宽度,可以容纳另一个操作数而不会丢失数据.这个缩小的字符串数字只是一个拙劣.

如果我们修复了这个问题,我们仍然会:

0 == "0"
1 == "1"
true != "1"
false != "0"

但是我们也会得到你的例子想要的东西:

true == "true"
false != ""

根据我对字符串转换的数字偏好的调用,我们不会有真==“1”或假= =“0”,因为它从字符串缩小到数字.确切地说,缩小不会丢失任何位,并且可以将0扩展回“0”并将1扩展回“1”,但是我想说明从==的隐式转换规范中删除所有字符串数字偏差的原因.

这样的改变会破坏网络上的很多代码吗?我敢打赌会有大笔金额.

有些人认为,除了引擎盖下的任何隐式转换之外,还有其他原因使用===和!==总是(因为它们永远不会转换),并完全避免==和!=.其他人不同意(特别是在测试x == null时,一种运算符的方法来测试x === null || x === undefined).

由于网络大多数兼容,直到非常旧的形式消失,我们仍然坚持使用==和!=,所以我说有必要了解操作平庸的运算符做什么.完成后,在我看来,人们可以在胜利的地方使用它们:当你知道操作数是同一类型时,例如

typeof x ==“function”等
x == null

否则,使用===和!==.

如果操作数是数字或布尔值,但这就是JS“工作”的方式: – |.

还有一点需要注意:可以说,从字符串到数字的缩小是可以的(如在大多数情况下有用,并且不安全),如果任何非数字,非空的字符串到数字的隐式转换尝试抛出一个例外.

这是JS设计中另一个与路径相关的偏差:JS1中没有try / catch,也没有任何ECMA-262标准,直到ES3.

缺少异常处理也意味着undefined被归为缺少obj.foo属性get,其中obj没有这样的属性.这仍然是令人讨厌的,可能与隐含的转换咬合=或多.它也是web JS赢得“对象检测”模式的基础,它与我见过的所有其他版本控制方案相当,特别是基于显式编号和选择加入的先验版本.

如果我只是花时间为对象检测添加一个存在运算符,那么就可以编写

function emulateRequestAnimationFrame(...) {...}
if (!window.requestAnimationFrame?)
  window.requestAnimationFrame = emulateRequestAnimationFrame;

IOW,如果只是我做了window.noSuchProperty throw但是window.noSuchProperty?评估为真或假(细节仍然是TBD,参见“失败快速对象解构”线程复兴,Nil的想法).

猜你在找的JavaScript相关文章