本文深入解析JavaScript中的隐式类型转换机制,涵盖一元运算符、逻辑非、位运算及加号运算符的转换规则。重点阐述相等运算符(==)与严格相等(===)在null、undefined、NaN及对象比较中的差异,通过具体代码示例说明字符串、数字、布尔值之间的自动转换逻辑,帮助开发者避免常见的类型陷阱。
JavaScript隐式类型转换机制详解
引言部分
[] == ![] //true ==> "" == false
123 ^ [] //123 ==> 123 ^ 0
~{} //-1 ==> ~0
{} >= {1,2} //true ==>因为大于等于的比较,不是相等的比较,所以[object Object] >=[object Object]
[null] == "" //true ==> [""] == ""
一元、逻辑与位运算的转换规则
关键运算符说明:
一元运算符:利用Number()执行转换;涵盖乘法(*)与除法(/)运算符,均通过Number()进行类型转换
+undefined //NaN
逻辑运算符:!等同于Boolean(),对操作数执行布尔类型转换
位运算符:~, |, &, ^;若任一操作数为NaN,可视为0参与运算
//由以下变化可以证得:
NaN ^ NaN ^ NaN = 0
加号与减号运算符的复杂转换逻辑
加法运算符,逻辑较为复杂
字符串优先级最高,任何操作数与字符串相加时,均通过String(x)转为字符串后执行拼接
console.log("a" + 1); //"a1"
console.log("a" + "1"); //"a1"
console.log("a" + false); //"afalse"
console.log("a" + undefined); //"aundefined"
console.log("a" + NaN); //"aNaN"
console.log("a" + null); //"anull"
console.log("a" + {}); //"a[object Object]"
其次是Number类型,而Object在常规情况下输出为String类型
//console.log(1 + "1"); //"11"
console.log(1 + 1); //2
console.log(1 + true); //2
console.log(1 + undefined); //NaN
console.log(1 + NaN); //NaN
console.log(1 + null); //1
console.log(1 + {}); //"1[object,Object]"
若一方或双方为Boolean,均执行Number处理;undefined与null同理
console.log(true + true); //2
console.log(true + undefined); //NaN
console.log(true + NaN); //NaN
console.log(true + null); //1
console.log((true + [NaN])); //"trueNaN"
减法运算符,对两侧操作数均执行Number()处理
相等运算符与比较运算的核心规则
比较运算:==, >, <, >=, >=, != 遵循以下规则(参考《JavaScript高级程序设计》第3版):
1. null与undefined相等
2. 比较前,不得将null和undefined转换为其他任何值
3. 若存在NaN操作数,相等运算符返回false,不相等运算符返回true,且NaN不等于NaN
4. 两个对象比较时,若指向同一对象(内存地址相同),相等运算符返回true,否则返回false
注意:对象间的>=与==(!=)比较机制不同,前者比较toString()返回值,后者比较引用地址
当两侧均为字符串时,按字符编码值大小进行比较
当一侧操作数为boolean、string或object时,先转换为number类型数值再进行比较;
console.log("NaN" == NaN); //false
console.log(undefined == null); //true
console.log({} >= {1:2}); //true
console.log({1:2} != {}); //true
console.log({} == {1:2}); //false
console.log([1] == [1]); //false
console.log(null == 0); //false