JavaScript深入之头疼的类型转换(上) JavaScript深入之头疼的类型转换(下)
对象转原始值
包含隐式转换和显式转换。内部都是调用
ToPrimitive方法;区别是隐式转换除了Date对象是转换成字符串,其他都是转换成数字;转换规则见下面。而显式转换则根据需要转换成对应原始值。
// 这里是显式转换:相当于Number(new Date()) -> new Date().valueOf()
+new Date() // 1664215006384
// 这里是隐式转换:10+new Date().toString()
10+new Date() // '10Tue Sep 27 2022 01:58:41 GMT+0800 (中国标准时间)'
对象转数字:
先调
valueOf方法,能转换成原始类型则直接返回,不能则再调toString方法;还是不能则报错。
对象转字符串:
先调
toString方法,能转换成原始类型则直接返回,不能则再调valueOf方法;还是不能则报错。
对象转原始值的原理都是调内置 ToPrimitive
**语法:`ToPrimitive(input[, PreferredType])`**
- 第一个参数 `input`,表示要处理的输入值。
- 第二个参数 `PreferredType`,非必填,表示希望转换成的类型,有两个值可以选,Number 或者 String。
- PreferredType 不传时,如果 `input` 是日期类型,相当于传入 String,否则,都相当于传入 Number;**即:不传第二个参数时,对象转原始值除了 `Date` 对象默认先调 `toString`,其他对象都是默认先调` valueOf`**
- 如果 `input` 传的是 `Undefined、Null、Boolean、Number、String` 类型,直接返回原值。
console.log(Number({})) // NaN
console.log(Number({a : 1})) // NaN
console.log(Number([])) // 0
console.log(Number([0])) // 0
console.log(Number([1, 2, 3])) // NaN
console.log(Number(function(){var a = 1;})) // NaN
console.log(Number(/\d+/g)) // NaN
console.log(Number(new Date(2010, 0, 1))) // 1262275200000
console.log(Number(new Error('a'))) // NaN
需要注意的是: new Date().valueOf()返回时间戳 , new Date().toString()返回时间格式字符串
new Date().toString() // "Fri Aug 19 2022 16:42:43 GMT+0800 (中国标准时间)"
new Date().valueOf() // 1660906740870
二元操作符 +
- 两边都是基本数据类型:
- 出现字符串就是字符串拼接;
- 否则都是隐式转换成数字类型再计算;
- 两边出现有复杂类型:
- 先把复杂类型调内置方法
ToPrimitive方法(除了Date类型其他都是转换成数字类型,即:都先调valueOf方法,没转换成功再调toString方法;Date类型相反。); - 然后再进行运算;
- 先把复杂类型调内置方法
console.log(null + 1); // 0+1 = 1
console.log([] + []); // [].toString() + [].toString() = '' + '' = ''
console.log([] + {}); // [].toString() + ({}).toString() = '' + '[object Object]' = '[object Object]'
console.log([] + new Date()); // [].toString() + new Date().toString() = '' + 'Mon Aug 22 2022 18:49:59 GMT+0800 (中国标准时间)' = 'Mon Aug 22 2022 18:49:59 GMT+0800 (中国标准时间)'
console.log({} + new Date()); // [].toString() + new Date().toString() = '[object Object]' + 'Mon Aug 22 2022 18:49:59 GMT+0800 (中国标准时间)' = '[object Object]Mon Aug 22 2022 18:49:59 GMT+0800 (中国标准时间)'
双登号隐式类型转换
双登号隐式类型转换总结:转换的目的是转换成相同类型来比较;转换不了相同类型直接返回false
null和undefined不进行双登号隐式转换; 且null == undefined -> true- 出现布尔值,先把布尔值转换成数字类型:
true -> 1,false -> 0; - 出现字符串:
- 另一边也是原始值类型时候:先把字符串转换成数字类型:
Number(string); - 另一边是复杂类型时,是先把复杂类型调用内置方法
ToPrimitive方法转换成字符串再比较;
- 另一边也是原始值类型时候:先把字符串转换成数字类型:
console.log(66 == ['66']) // true
console.log(false == "0") // true
console.log(false == 0) // true
console.log(false == "") // true
console.log(false == []) // true
console.log(false == ['']) // true
console.log(false == ['0']) // true
// null, undefined 特殊,不会转换成数字或字符串去比较,始终保持原值;
console.log(null == undefined) // true
console.log(false == null) // false
console.log(false == undefined) // false
console.log("" == 0) // true
console.log("" == []) // true
// [undefined].toString() = ''; [null].toString() = ''; [false].toString() = 'false'; [NaN].toString() = 'NaN'; [0].toString() = '0'; [''].toString() = '';
console.log("" == [null]) // true
console.log("" == [undefined]) // true
console.log(false == [null]) // true
console.log(false == [undefined]) // true
// +'\n' = 0; +'\r' = 0;
console.log(0 == "\n") // true
console.log(0 == "\r") // true