类型转换笔记

108 阅读3分钟

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

二元操作符 +

  • 两边都是基本数据类型:
    • 出现字符串就是字符串拼接;
    • 否则都是隐式转换成数字类型再计算;
  • 两边出现有复杂类型:
    1. 先把复杂类型调内置方法 ToPrimitive 方法(除了Date类型其他都是转换成数字类型,即:都先调 valueOf 方法,没转换成功再调 toString 方法; Date 类型相反。);
    2. 然后再进行运算;
  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

  • nullundefined 不进行双登号隐式转换; 且 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