隐式类型转换
通过这篇文章,你会了解到隐式类型转换的本质。
虽然在平时项目中我们避免去使用==,但是在面试中却总被问到这类题目,每次都是一脸懵,终于静下心来去总结了这篇文章,希望对你有帮助。
非严格匹配: 会类型转换,但是有前提条件一共有六种情况(示例以x == y说明)。
x和y都是null或undefined
规则: 没有隐式类型转换,无条件返回true
console.log (null == undefined); // true
console.log (null == null); // true
console.log (undefined == undefined); // true
x或y 有一方是null或undefined
规则: 没有隐式类型转换,无条件返回false
console.log (null == []); // false
console.log (null == 123); // false
console.log (undefined == ''); // false
console.log (undefined == {a: 123}); // false
x或y是NaN : NaN与任何数字都不等
规则:没有隐式类型转换,无条件返回false
console.log (NaN == NaN); // false
x和y都是string,boolean,number
规则:有隐式类型转换
(1) string => number
会通过Number()方法将string类型的数据转成number
(2) boolean => number
先调用Boolean(),再调用Number()
console.log(1 == true); // true
(1) 1 == Number(true)
console.log(1 == "true"); // false
(1) 1 == Number('true')
(2) 1 == NaN
console.log(1 == !"true"); // false
(1) !运算符会将变量转换为Boolean类型
(2) 1 == !Boolean('true')
(3) 1 == false
(4) 1 == Number(false)
(5) 1 == 0
console.log(true == 'true') // false
(1) Number(Boolean(true)) == Number('true')
(2) 1 == NaN
x或y 有一方是复杂数据类型
规则:有隐式类型转换,会先获取复杂数据类型的原始值之后再做比较
获取原始值:先调用valueOf(),在调用toString()方法
// 注意
console.log([].valueOf().toString()); // 空字符串
console.log({}.valueOf().toString()); // [object Object]
console.log({} == '[object Object]'); // true
console.log([1,2,3] == '1,2,3'); // true
(1) [1,2,3].valueOf().toString() == '1,2,3';
(2) '1,2,3' == '1,2,3'
console.log([] == true); // false
(1) [].valueOf().toString() == Boolean(true)
(2) Number('') == Number(true)
(3) 0 == 1
console.log([1] == 1); // true
(1) [1].valueOf().toString() == 1;
(2) '1' == 1;
(3) Number('1') == 1;
x和y都是复杂数据类型
规则:只比较地址,如果地址一致则返回true,否则返回false
const arr1 = [10,20,30];
const arr2 = [10,20,30];
const arr3 = arr1; // 将arr1的地址拷贝给arr3
console.log (arr1 == arr2); // 虽然arr1与arr2中的数据是一样,但是它们两个不同的地址
console.log (arr3 == arr1); // true 两者地址是一样
console.log([] == []); // false
console.log({} == {}); // false
转换特殊情况
转换为布尔值时的假值有:undefined、null、空字符串、0、-0、NaN,其余例如{}、[]都是真值
console.log([] == ![]) // true
(1) [] == !Boolean([])
(2) [] == false
(3) [].valueOf().toString() == Number(Boolean(false))
(4) '' == 0
(5) Number('') == 0
(6) 0 == 0
console.log({} == !{}) // false
(1) {} == !Boolean({})
(2) {} == false
(3) {}.valueOf().toString() == Number(Boolean(false))
(4) [object Object] == 0;
(5) Number([object Object]) == 0
(6) NaN == 0
// 数组元素为null或undefined时,该元素被当做空字符串处理
[null] == false // true
[undefined] == false // true
常用特殊运算符
加号运算符(+)
若+两边存在一个字符串,将另一个也转为字符串进行字符串拼接
其他情况下,都转为数值类型
console.log(1 + '2'); // 12
console.log(1 + + '2') // 3 一元加法运算符把操作数转换为数字(或者NaN),并返回这个转换后的数字 +'2'转换为数值2
console.log([1,2,3] + []); // "1,2,3"
(1) "1,2,3" + ""
(2) "1,2,3"
console.log([] + {}); // "[object Object]"
(1) "" + "[object Object]"
(2) "[object Object]"
减号运算符(-)
减号 - 将两边都转换成数值类型,不能连接字符串
console.log('aaa' - 11); // NaN
console.log(11 - 'aaa'); // NaN
console.log(1 - - '2'); // 3 相当于 1 - (-2)
console.log(-'1' - '2'); // -3 相当于 -1 - 2
非运算符(!)
逻辑非 ! 将其后变量或表达式转为布尔值
console.log(1 == !"true"); // false
(1) !运算符会将变量转换为Boolean类型
(2) 1 == !Boolean('true')
(3) 1 == false
(4) 1 == Number(false)
(5) 1 == 0
console.log({} == !{}) // false
(1) {} == !Boolean({})
(2) {} == false
(3) {}.valueOf().toString() == Number(Boolean(false))
(4) [object Object] == 0;
(5) Number([object Object]) == 0
(6) NaN == 0
各类型的toString()、valueOf()方法的返回值(理解就好)
对象
toString() => "[object Object]"
valueOf() => 对象本身
const a = {b: 1};
a.toString(); // "[object Object]"
a.valueOf(); // {b: 1}
数组
toString() => this.join()的返回值
valueOf() => 数组本身
const a = [1,2,3];
a.toString(); // "1,2,3"
a.valueOf(); // [1, 2, 3]
方法
toString() => 整个函数字符串
valueOf() => 方法本身
const a = function() {
return 111;
};
a.toString(); // "function(){return 111;}"
a.valueOf(); // ƒ (){return 111;}
日期
toString() => 完整事件字符串
valueOf() => 从1970年1月1日0时0分0秒(UTC,即协调世界时)到该日期的毫秒数。
const a = new Date();
a.toString(); // "Thu Mar 07 2019 13:48:31 GMT+0800 (中国标准时间)"
a.valueOf(); // 1551937711874
😊 欢迎提出宝贵的建议,一起进步学习。