再也不惧怕面试时被问到 js隐式类型转换 ~

335 阅读4分钟

隐式类型转换

通过这篇文章,你会了解到隐式类型转换的本质。

虽然在平时项目中我们避免去使用==,但是在面试中却总被问到这类题目,每次都是一脸懵,终于静下心来去总结了这篇文章,希望对你有帮助

非严格匹配: 会类型转换,但是有前提条件一共有六种情况(示例以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

😊 欢迎提出宝贵的建议,一起进步学习。