Javascript 类型转换

95 阅读5分钟

数据类型转换又分为显式转换和隐式转换

显式转换如: 构造函数、parseInt、parseFloat、toString等,顾名思义,很明显就能判断出会被转换成什么数据类型

隐式转换如: == 、 < 、 > 、 + 等, 需要考虑操作的元素,如 == 判断两边的类型不同还会进行不同的转换以后进行比较,参考关系运算符

尽量使用===,避免类型转换考虑不全带来的异常行为,但是还是需要对隐式转换有所了解,可以加深你对类型转换的理解并且在项目中如果碰到也不会一脸懵。

string

将其他类型转换成string一般采用 ''+(和字符串拼接)、String()、toString()

演示
// 1. 拼接字符串 ''+
console.log('' + 1024);      // '1024'
console.log('' + true);      // 'true'
console.log('' + false);     // 'false'
console.log('' + null);      // 'null'
console.log('' + undefined); // 'undefined'
console.log('' + 1024n);     // '1024'

// 相当于调用Object.prototype.toString.call()
console.log('' + {});        // '[object Object]'

// 数组转换成字符串, 使用','将拼接每一项形成字符串,空数组[]转换成''
console.log('' + []);        // ''
console.log('' + [1]);       // '1'
console.log('' + [1,2,3]);   // '1,2,3'

// 数组转换成字符串, null和undefined会被转换成''
console.log('' + [null]);      // ''
console.log('' + [undefined]); // '' 

// 相当于调用join(',')
console.log([1,2,3].join(',') === '' + [1,2,3]); // true

// 2. String() 
// 转换和拼接字符串基本一致
// 不同点:
// Symbol可以使用String()转换成stirng,不能使用+转换
console.log('' + Symbol());    // TypeError: Cannot convert a Symbol value to a string - 类型异常: 不能将Symbol转换成string
console.log(String(Symbol())); // Symbol()

// 3. toString()方法
// 除了null和undefined,其他的数据都可以调用toString()方法
// 如果忘记了基本数据类型为什么可以调用方法以及为什么null和undefined不能调用,可以复习一下基本数据类型
console.log(false.toString());    // false
console.log({}.toString());       // [object Object]
console.log([1,2,3].toString());  // 1,2,3

console.log(undefined.toString()); // TypeError: Cannot read property 'toString' of undefined - 类型异常: 不能从undefined上读取toString
console.log(null.toString()); // TypeError: Cannot read property 'toString' of null - 类型异常: 不能从null上读取toString

number

将其他类型转换成number一般采用 +、Number()、parseInt和parseFloat

string -> number

使用常见的方式将string转换成number

// 1. +
// 忽略前后空格,不仅可以转换整数,还可以转换浮点数
console.log(+'    1024.2    ');  // 1024.2
// 无法转换成数字,则返回NaN
console.log(+'1024Number'); // NaN, 尽管前面的1024可以转换,但整个字符串无法转换

// 注意: 特殊值的字符串可以转换成number
console.log(+'Infinity'); // Infinity
console.log(+'NaN');      // NaN, 至于这个是转换成功的NaN还是失败的NaN不那么重要

// 2. Number()
// 忽略前后空格,不仅可以转换整数,还可以转换浮点数
console.log(Number('    1024.2    '));
// 无法转换成数字,则返回NaN
console.log(Number('1024Number')); // NaN, 尽管前面的1024可以转换,但整个字符串无法转换


// 3. parseInt和parseFloat
// 这两个方法除了被挂载在全局对象,也被挂载在 Number上
console.log(Number.parseFloat === parseFloat);  // true
console.log(Number.parseInt === parseInt);  // true

// 忽略前后空格,并且会省略小数部分
console.log(parseInt('   1024.2   ')); // 1024
// 忽略空格后,从头开始匹配数字,直至非数字字符为止,将匹配的部分转换成数字,匹配部分如果为空,返回NaN
console.log(parseInt('   1024.2N   ')); // 1024, 截止1024部分都是数字字符串,N不满足
console.log(parseInt('   N1024.2   ')); // NaN, 开头N直接不满足,转换成NaN
其他转换

演示其他数据类型转换成number

console.log(+'');        // 0
console.log(+true);      // 1
console.log(+false);     // 0
console.log(+null);      // 0
console.log(+undefined); // NaN

// BigInt可以通过Number转换,不能使用+转换
console.log(+1024n); // TypeError: Cannot convert a BigInt value to a number - 类型异常: 无法将BigInt转换成number
console.log(Number(1024n)); // 1024

// 数组和对象转换成number,先调用[Symbol.toPrimitive]函数, 如果没有,则执行toString()
console.log(+{});     // NaN, {}先被转换成[object Object],相当于 +'[object Object]'

// 数组转换number,需要先将其转换成string,再转换成number
console.log(+[]);             // 0,    []先被转换成'',相当于 +''
console.log(+[null]);         // 0,    [null]先被转换成'',相当于 +''
console.log(+[undefined]);    // 0,    [undefined]先被转换成'',相当于 +''
console.log(+['1024']);       // 1024, ['1024']先被转换成'1024',相当于 +'1024'
console.log(+['1024','64']);  // NaN,  ['1024','64']先被转换成 '1024,64', 相当于 +'1024,64'

boolean

将其他类型转换成boolean一般采用 !!、Boolean()

// JS存在的falsy(假值)全在这了
console.log(false);
console.log(!!0); // 包括 +0、-0、0n
console.log(!!null);
console.log(!!undefined);
console.log(!!'');
console.log(!!NaN);

// 除了以上的值转换成false,其他值转换成boolean时,皆为true
console.log(!!10);      // true
console.log(!!'0');     // true, 注意:这个是字符串,只有空字符串''才会转成false
console.log(!!'false'); // true, 注意:这个是字符串,只有空字符串''才会转成false
console.log(!![]);      // true,和转换成number不一样,不会先转换成string
console.log(!!{});      // true

object -> 基本数据类型

从object转换成基本数据类型并不都是调用toString(),还有[Symbol.toPrimitive]()以及valueOf()

优先级为[Symbol.toPrimitive] > valueOf > toString

这三个函数至少得有一个返回基本数据类型,否则会报错,如果不写return,默认返回的undefined是基本数据类型

const obj  = {
  [Symbol.toPrimitive](){
    return 'toPrimitive';
  },
  valueOf(){
    return 'valueOf';
  },
  toString(){
    return 'toString'
  },
}

//  此时三种方式都存在, 返回Symbol.toPrimitive的值
console.log(''+obj); // toPrimitive
delete obj[Symbol.toPrimitive];  // 移除Symbol.toPrimitive方法

// 此时只剩 toString 和 valueOf
console.log(''+obj); // valueOf
delete obj.valueOf;  // 移除valueOf方法

// 只剩toString
console.log(''+obj); // toString

面试题

  • 定义变量n,使 n == 1 && n == 2 && n == 3 成立
// 既然知道了可以控制对象转换成基本数据类型的行为,那么这就非常简单了
const n = {
  num : 1,  // 存储数字
  [Symbol.toPrimitive](){
    return this.num ++; // 每次换成基本数据类型的时候,num都加1
  }
};
// 注意,==会触发类型转换,===不会
// 每次判断以后num都+1,所以每次判断都相等
console.log(n == 1 && n == 2 && n == 3); // true

参考