前端架构系列

类型转换

2020-06-24  本文已影响0人  羽晞yose

js中,涉及类型转换主要有以下几种:

if()

将内容转换为布尔值,为false的值包括:false undefined null ‘’ 0 NaN

!

把值转换成布尔值,为true的值包括:0 null undefined NaN '' false,其他的均为false(可能有纰漏,没找到什么统计文章)

+(加) -(减)符号

具有将值转换为数值类型,会将类型转换为number

console.log(typeof +'a'); // number
console.log(1+ +'123'); // 124,先将'123'转换为数值,再执行相加

运算符: +、-、*、/、%、++(递加)、--(递减)

在js中,当运算符在运算时,如果两边数据不统一,CPU就无法计算,这时我们编译器会自动将运算符两边的数据做一个数据类型转换,转成一样的数据类型再计算

这里先列一下各种值在Number()执行后的结果,下面需要用到(当然底层实现并不完全是通过Number来判断的,否则1+{}就不会是1[object Object]了)

Number([]); // 0
Number(''); // 0
Number(null); // 0
Number(false); // 0
Number('1'); // 1
Number(Infinity); // Infinity
Number('1a'); // NaN
Number(undefined); // NaN

可以稍微总结一下(或许有纰漏):
空数组、空字符串、null、false转换为数值为0
纯数字字符串可以转换为数值,否则为NaN
infinite转换为数值为infinite
其他的基本为NaN(如上所说,可能有纰漏,所以用词:基本)

除了+号,其他运算符都是直接将非数值类型转换为数值运算
而+号有两个功能:运算 / 字符串拼接(如果有一方为字符串,则会变为字符串拼接)
运算,可以分为以下两类:

  1. 数字和非字符串相加
1+null; // 1
1+undefined; // NaN
1+{}; // 1[object Object],具体原因往下看
  1. 非数字相加
true+true; // 1
true+{}; // true[object Object]

上面内容也可以看到,{}使用Number()会返回NaN,但是在+号运算符下他却变成[object Object]的字符串类型

这是因为对象中有两个方法 valueOf() 和 toString(),在运算时,先执行valueOf方法,如果结果不是原始数据类型,那么会继续执行toString方法,如果还不是原始数据类型,那么就会抛出错误。
ES6新增[Symbol.toPrimitive],对象被转为原始类型的值时,会调用[Symbol.toPrimitive]方法,返回该对象对应的原始类型值。

可以通过以下改写方法来测试一下执行结果

let obj = {
    valueOf () {
        return 200; // 对象的valueOf会返回自身,所以这里改回{},就会输出300
    },
    toString() {
        return 300;
    }
}

console.log(true+obj);

所以总结起来,对于转换为数值类型,底层原理就是:先将非数值类型值调用valueOf方法,如果返回的不是基本类型值,继续调用toString方法
Q:为什么1/{}结果会是NaN,1+{}会是1[object Object],能解释出来了吗?
A:因为对象转换为基本类型值是'[object Object]',所以1/一个字符串,结果返回NaN,而+号具有字符串拼接的功能,所以1+{}返回1[object Object]

比较运算: > == <

console.log('a' < 'bbb'); // true,比较左右两边首字母ascii码
console.log('a'.charCodeAt(0)); // 97
console.log('b'.charCodeAt(0)); // 98
console.log(1 < 'aaa'); // false,因为aaa转换为数值为NaN
console.log(1 < '123'); // true
  1. 对象与对象比较,比较的是命名空间
    {} == {}; // false
  2. NaN和任何类型比较都不相等,包括它自身
    NaN == NaN; // false
  3. 如果有Boolean类型,会把Boolean转换为数字
    1 == true; // true
  4. 对象 和 字符串/数字/symbol比较,会把对象转换为原始数据类型
    {} == '[object Object]; // true

Q: [] == ![],结果是什么?能否解释一下?
A: true,首先有!,单目运算符优先级最高,所以会先将![]转换为布尔值,结果为false,false为布尔值,布尔值转换为数字,结果为0,所以到这里结果变成 [] == 0,对象与数字比较,会将数字转换为原始类型,所以比较结果变成 '' == 0,空字符串转换为0,所以结果为true

下一篇加深的文章:数据类型的细节知识,配合阅读,效果更佳

拓展阅读:
js面试题大坑——隐式类型转换
https://github.com/jawil/blog/issues/1
toString方法和valueOf方法以及Symbol.toPrimitive方法的学习

上一篇下一篇

猜你喜欢

热点阅读