[JavaScript 随笔] 理解严格相等、非严格相等和隐式类型转换

news/2024/6/22 20:58:09

JavaScript 中大概有这几种 “类型”

  • undefined

  • null

  • string

  • boolean

  • number

  • object

  • function

之所以在 “类型” 上加了双引号,是因为严格来说,null 的类型是 object。但本文讨论的主题包括了关于 null 的类型转换,它和 object 不同,所以单独列出来了。这点请根据上下文强行区分一下,不是bug、不是bug、不是bug。

有趣的例子

'0' == 0;  // true
0   == ''; // true
'0' == ''; // false

这里展示的是相等比较的非传递性。即,如果有 a == b, b == c,并不代表 a == c。

如果说

'1' == true;
'0' == false;

这两个是常识,那对于一些特殊的字符串,你能正确判断吗?

'001' == true;
'002' == false; // 注意!
'0x0' == false;
'\n'  == false;

非严格相等(==)

当使用 == 比较,并且两侧的类型不同时,会触发隐式类型转换。标准中定义的转换规则很长,其核心就是,1、类型不同时,尽量转成 数字 比较;2、特例。(类型相同就按该类型的值判断,不特殊说明了,难道 '123' 还能等于 '456' 不成?)

关于特例,其实也就是 null 和 undefined 。也就是说,以下几个表达式是永远为 true 的。

undefined == null;
null      == undefined;
NaN       != NaN;    // 注意!
null      != 非null; // 注意!null 与非 null 值永远是不等的

所以也不需要再去深追为什么 undefined 和 null 是相等的,因为按照“规则”已经无法解释了,这是一种“约定”。OK,剩下的情况是转数字。

  • null 的数值是 0

  • undefined 的数值是 NaN

  • true 是 1,false 是 0

  • 至于字符串,嗯,有点复杂

  • object:调用 toString 或 valueOf 后转成基本类型,再转数字

第一条,在这里没用,因为涉及到 null 的比较时,除非 null == null,其他情况都是不等的。即

null != 0;

第二条,在这里没用,因为涉及到 NaN 的比较时,都是不等。

第三条,有点用,很有用!

1 == true; // 对
2 == true; // 错!

第四条,麻烦。80% 情况下,对于 '123' 转成 123,'abc' 转成 NaN,'' 转成 0,这三条记住就可以了。

'123' == 123;
''    == 0;
'abc'; // 转成数值是 NaN

另外的情况,由于字符串的组合形式各种各样,很难三言两语总结完,大致有:

  • 空白字符串转成 0,'\n' == 0

  • 十六进制、八进制正常转换,'0xff' == 255

  • 数字字符串会忽略首尾空白字符,正常转,'\n123\n' == 123

  • 数字字符和其他字符混合时,转成 NaN,如 '123abc'

现在回头去看“有趣的例子”,是不是一目了然。(嗯,不谢)

条件判断

暂且把 if - else 和 condition ? a : b; 中的判断情况称为条件判断吧。(场景还有取反、for、while 等)

等于 true 的值一定是 truthy,但等于 false 的值不一定是 falsy 。

new Boolean(false) == false;    // 这个没问题吧?
new Boolean(false) ? 'a' : 'b'; // 表达式的值是 'a'!

只能说,条件判断中对真假的判定和相等判断是不一样的。 显然,相等判断是基于数字比较的,而条件判断是基于布尔值。

关于布尔值的转换规则:

  • null, undefined, NaN 都是 false

  • 字符串,仅当空字符串('')时为 false,其他都是 true

  • object,都是 true (仅 null 除外)

我见过其他一些相等判断的技巧:

!!x == true;
+x  == 123;

取反操作会把变量强转成 boolean;一元 + 会把变量强转成 number。

也见过一些用的不太合适的地方(?):

if (!!x) // ...

在条件判断中本身会做强转的操作,为了可读性?不见得有提高。

严格相等(===)

严格相等的逻辑相对简单粗暴,如果类型不同,就不考虑隐式转换了,直接为假。如果类型相同:

  • 布尔、数字、字符串就看字面值是否相等

  • object,看引用是否相同

主要是考虑什么时候用 ==,什么时候用 === 。

很简单,只有在要求类型相同时,才用 ===,否则用 ==

有些场景的确只有非严格相等才能做,比如

var b = new Boolean(false);
b === false   // 竟然是错的
b == false    // 对
b ? 'a' : 'b' // 竟然是 'a'

结论就是当涉及到对象比较时,稍微斟酌一下。而对于像 typeof x 它一定会返回 string,这时用 == 比较就更合适一些。

小结

涉及到 == 比较,并且需要隐式转换时,会转成 number。

涉及到条件判断,自然是转成 boolean。

涉及到二元 +、- 等数值计算时,从左至右优先转成 number,除非是遇到 string,则做字符串拼接操作。


http://www.niftyadmin.cn/n/1974381.html

相关文章

大数据看板及模板

本来想放个百度网盘的连接的,网盘不给力没办法,还真的有同学私信我了,找到了网盘不能生成链接的原因了,是因为我想直接生成压缩包的链接,所以一直报错,现在给外边加了个文件夹! 链接: 点击下载

2014-11-6Android学习------activity切换特效--------动画Animation学习篇

写一篇文章很辛苦啊!!! 转载请注明,联系请邮件nlp30508qq.com 我学习Android都是结合源代码去学习,这样比较直观,非常清楚的看清效果,觉得很好,今天的学习源码是网上找的源码 百度搜…

springDataJpa 逆向生成实体类图文详解

前言 最近做了几个小demo 是关于sprongDataJpa 的整个框架中用的都是spring的产品也就是全家桶。 通过数据库生成Entity实体,也可以通过Entiy实体转换成数据库表。这里主要说一下,怎样通过数据库表生成Entity实体。所有的操作都是在idea环境下进行的。 …

善变的不只是女人,还有volatile ---偷来的标题名

下面代码包括 2 个函数,第一个函数是中断服务程序用于从温度传感器中读 取数据,第二个函数比较温度是否一致。它是否包括错误?如有,该如何修正? 1 static int iTemperatures[2];2 3 void __IRQ__vReadTemperatures(voi…

Java线程:总结

线程的状态转换图: new:新建状态 Runnable:就绪状态。线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。 Running:运行状态…

class文件的反编译过程

前言 这几天由于工作需要进行了一些反编译的工作,之前的同事离职了,负责的项目代码转交给我,这个项目好长时间没有用了,在看源码的过程中发现里边少了几个类,几经周折找到了以前编译好的jar包。要想恢复就智能进行反编…

2014-11-6Android学习------Spinner下拉选择框控件学习

写一篇文章很辛苦啊!!! 转载请注明,联系请邮件nlp30508qq.com 我学习Android都是结合源代码去学习,这样比较直观,非常清楚的看清效果,觉得很好,今天的学习源码是网上找的源码 百度搜…

诡异的 unnest 函数

为什么80%的码农都做不了架构师?>>> 发现函数 unnest 定义如下: CREATE OR REPLACE FUNCTION unnest(anyarray)RETURNS SETOF anyelement AS array_unnestLANGUAGE internal IMMUTABLE STRICTCOST 1ROWS 100; 为了可读性,这是还原…