Example. JavaScript 隐式转换与相等三角图

JavaScript 遇到 true + 1 true + 1 时明确规定把 true true 转成 1 1 再相加,得到 2 2 . 同样,宽松相等 == == 规定了按两边种类进行转换的规则; 严格相等 === === 则不做这种转换,不同种类的操作数直接判为不相等. 把两种比较放在一起看:

true + 1;    // 2:true 转换为 1

[] == 0;     // true
[] === 0;    // false
0 == "0";    // true
0 === "0";   // false
[] == "0";   // false
[] === "0";  // false
true + 1;    // 2:true 转换为 1

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

图中每条边同时记录 == == 和 === === 的比较结果(注意边代表相等比较,无方向,不同于规约箭头). 绿色实线表示 == == 为真,红色虚线表示 == == 为假; 第二行单独记录 === === ,这里三条边都为假.

[] == 0 [] == 0 会先把空数组转换成空字符串 "" "" ,再因另一边是数字而把 "" "" 转成 0 0 ; 0 == "0" 0 == "0" 会把字符串 "0" "0" 转成数字 0 0 ,所以这两条边都为真. 但 [] == "0" [] == "0" 把数组转成 "" "" 后,两边已经都是字符串,只比较 "" "" 与 "0" "0" ,结果为假. 具体转换规则见 MDN 的 == == 文档.

传递性要求:𝑎 与 𝑏 相等、𝑏 与 𝑐 相等,就能推出 𝑎 与 𝑐 相等. 这个三角图正好展示 == == 不满足传递性,不能像数学等号那样用于替换或推理. === === 省略了跨种类的类型转换:数组、数字、字符串种类不同,所以这三个比较都为假. 它和 == == 采用的是两套不同的判准.

即便如此, === === 仍与完整的数学等价关系有别. 自反性要求每个值都与自身相等,而 NaN === NaN NaN === NaN 为 false false . 对对象, === === 只看两边是否指向同一个对象,不比较内部内容: const a = []; a === a const a = []; a === a 为 true true , [] === [] [] === [] 却为 false false , 因为后者创建了两个不同的数组. 严格相等的完整规则见 MDN 的 === === 文档.