【You Don't Know JS: Types & Grammar】Chapter 4-3 笔记

宽鬆相等 与 严格相等

宽鬆相等(==)允许相等比较中的强制转型,严格相等(===)则不允许强制转型。

如果比较的是相同型别的值,== 与 === 使用相同的演算法。

若比较的是不同型别的值,应该要确认,是否想要强制转型。

若想强制转型,就使用==相等性;若不想,则使用===相等性。

如果被比较的值具有相同的型别,它们就会以同一性(Identity)来比较。42只会等于42,"abc"只会等于"abc"。

少数例外:

NaN永远不等于自己+0 与 -0 相等

比较object(function和array),只有在它们都指向同一个值的参考,才会相等。

使用==相等性来比较,若2边的型别不同,其中之一(或2者)会进行隐含地强制转型成相同型别,再进行值的同一性比较。

!=宽鬆不相等,反转==的比较结果;!==严格不相等,反转===的比较结果。

比较:字串与数字

http://img2.58codes.com/2024/201125730aKg2Iiu1m.jpg

a === b会失败,因为===不允许转型。

a == b成功,意味着,它们转型成相同的型别比较,那究竟是42转"42",还是"42"转42呢?

以ES5的规格指出,"42"会被强制转型成number再进行比较。

比较:boolean与其他值

若试着将一个值与true/false做比较,有可能出现陷阱。

http://img2.58codes.com/2024/20112573iaPTG0bLAa.jpg

根据ES5的规格,如果其中一方是boolean的话,那就会强制转型成number做比较。

Example:
http://img2.58codes.com/2024/20112573Qr1T11BhtC.jpg

x是true(boolean),所以会强制转型成1(number),而"42"转型成42。1 == 42的结果很明显是flase。

http://img2.58codes.com/2024/20112573OcNz69L5sP.jpg

y=false,会变成42 == 0,结果也是flase。

问题来了,"42" == true"42" == false结果都是false,那"42"究竟是什么?

实事上,"42"的确是truthy,问题是出在相等性比较式,"42"是truthy值,拥有true的行为,但不会被转型成true,而true会被转型成1。切记,"42"再怎么转型,永远都不会是true。

所以"42"是truthy或flasy,跟==运算一点关係都没有。

不管在任何情况下,都不要使用== true== flase

=== true=== flase不会强制转型,所以不会有这个问题产生。

var a = "42";//会失败if (a == true) {// ..}//会失败if (a === true) {// ..}//会成功,隐含转型if (a) {// ..}//更好,明确转型if (!!a) {// ..}//一样会成功if (Boolean( a )) {// ..}

比较:null与undefined

null与undefined,以==相等性进行比较,会等于彼此,也等于自身,而且不相等于其他值。

var a = null;var b;a == b;// truea == null;// trueb == null;// truea == false;// falseb == false;// falsea == "";// falseb == "";// falsea == 0;// falseb == 0;// false

null与undefined在==相等性的情况下,彼此的强制转型是安全的,不会有其他的值导致误判情形。

善用null与undefined的特性:

var a = doSomething();if (a == null) {// ..}

以上的情形,只有在doSomething()回传null或undefined时,if判断式才会通过,即使是其他的false值也是失败。

var a = doSomething();if (a === undefined || a === null) {// ..}

使用===不允许强制转型的话,处理方式就没那么漂亮。

比较:物件与非物件

http://img2.58codes.com/2024/20112573LQJHKSi4IC.jpg

array是object,所以[42]会先强制转型成"42",再转成42,所以整个运算式会变成42 == 42。

容易引起麻烦的情况

"0" == false;// truefalse == 0;// truefalse == "";// truefalse == [];// true"" == 0;// true"" == [];// true0 == [];// true

以上的7种情况,都为true,我们来分析这7种情况。

"0" == false,false => 0,"0" => 0
false == 0,false => 0
false == "",false => 0," " => 0
false == [],false => 0,[ ] => 0
"" == 0," " => 0
"" == []," " => 0,[ ] => 0
0 == [],[ ] => 0

疯狂的例子

[] == ![];             // true2 == [2];       // true"" == [null];       // true

怎么会是true呢?

[] == ![]!运算子会先将[]转型成false,所以实际相等性比较是[] == false

2 == [2],object会先转基型值,[2] => "2" => 2。

"" == [null],[null] => " " => 0。

安全的隐含强制转型

请思考 == 相等性,另一边可能会出现的值。

如果比较的任一边有 truefalse[ ]" "0,就不要使用 ==

比较项目的图表,帮助记忆。
http://img2.58codes.com/2024/20112573tqTWRs5Iu8.png

来源:https://github.com/dorey/JavaScript-Equality-Table

抽象的关係式比较

若遇到a < b的情况,将2个运算元转型,若其中一方的结果不是string,那这2个值会强迫转成number,再进行数值的比较。

var a = [ 42 ];var b = [ "43" ];a < b;// trueb < a;// false

若2个值都是string,那就会进行字元的词典顺序比较。

var a = [ "42" ];var b = [ "043" ];a < b;// false

"42"会跟"043"逐字元作比较,第一个字元是"4"与"0"的比较,"0"在词典的顺序上小于"4",回传比较结果是false。

那这个呢?

var a = { b: 42 };var b = { b: 43 };a < b;//false

因为ab都会转成"[object Object]",所以比较上,没有谁大谁小的问题。

var a = { b: 42 };var b = { b: 43 };a < b;// falsea == b;// falsea > b;// falsea <= b;// truea >= b;// true

比较奇怪的是a == b,既然都是"[object Object]",应该要一样才对啊,各位不要被刚刚的a < b範例误导了。2个物件的比较,比的是「是否为同一个参考」。

依据规格,a <= b,会先估算b < a的结果(false),再否定其结果,所以a <= b会是true。

<=字面上的意思是「小于或等于」,但更精确的说法应该是「不大于」。所以a <= b被解读为!(a > b)再视为!(b < a)!false等同于true

a >= b先被视为b <= a,再解读为!(b > a),再一次视为!(a < b)!false等同于true

参考来源:
http://img2.58codes.com/2024/201125739FY75WdXxA.jpg

此为You Don't Know JS系列的笔记。


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章