隐式类型转换

先抛出简单结论

  1. 除了二元加是优先转字符串,其他情况遇到数字都是优先转数字类型;
  2. 布尔值会转换成数字。

细节则看下文。

正文

因为 JS 是弱类型语言,当遇到两个类型不同的值计算或逻辑比较等时,JS 底层会做隐式类型转换。

常见发生隐式类型转换的场景:一元加各种运算操作==>, <, >=, <=!xx等。

对象类型转原始类型

toPrimitive规则转换:

  1. 通常情况是:
    1. 先调用valueOf(),得到原始值则返回;
    2. 还是非原始值则继续调用toString(),得到原始值则返回;
    3. 还不能得到原始值则报类型错误:提示不能将该值转换成原始值。
  1. Date 对象是个特殊。它改写了toPrimitive:会优先调用toString(),不行再调用valueOf()
    1. 需要注意的是: 遇到强制类型转换时,比如:+new Date()此时则先valueOf(),因为这个方法返回的是数字类型。

注意: [null][undefined]的原始值都是''

1. 一元加 - ES5规范1.4.6

+xx

调用ToNumber处理值,相当于Number(xx)也可以理解成强制类型转换成数字。

xx为对象时,先按ToPrimitive规则将对象转换成原始值,再把原始值转换成数字类型。

1.1. 示例

scss 复制代码
+[]
[].valueOf() // 返回值还是 []
[].toString() // 返回''
Number('') // 0

1.2. 几个特殊的细节

  1. 遇到0b0o0x开头的:
    1. 会分别被当成二进制、八进制、十六进制,并返回对应十进制;
    2. 不管是字符串形式还是数字形式;
  1. 遇到多个0开头的:
    1. 字符串形式是去除前导0,返回剩余数字;
    2. 数字形式则当成八进制数,并转换成十进制数返回。
  1. 0b0o0x与后面的数字之间如果有数字会直接去掉。
arduino 复制代码
// 1. 示例
+0b100 // 4
+0o100 // 64
+0x100 // 256
+'0b100' // 4
+'0o100' // 64
+'0x100' // 256

// 2. 示例
+000100 // 64
+'000100' // 100
  
// 3. 示例
+0x000100 // 256
+'0x000100' // 256
+'0x00000' // 0

2. 各种运算符

2.1. 除了+之外的其他运算符

  1. 先把运算符两边的值转换成数字类型;
  2. 再进行计算。

2.2. 二元加 - 规范/#x11.6.1

规则:

  1. 出现字符串类型值时,把其他值都调toString()转换成字符串,然后字符串拼接;
    1. '' + xxx.toString()
    2. 注意: 同时出现有数字也是先把数字转换成字符串。这里跟==情况刚好相反。
  1. 先执行上面情况, 出现对象类型先把对象类型按ToPrimitive规则转换成原始值;此时的原始值通常都是字符串,所以执行字符串拼接;
  2. 先执行上面情况, 出现数字及其他非字符串的基本类型值时,把基本类型值转换成数字类型;
    1. 2 + Number(null)
  1. 先执行上面情况,出现布尔值,先把布尔值转换成数字。
    1. Number(true) + xxx
javascript 复制代码
console.log(1 + undefined); // NaN
console.log('1' + undefined); // '1undefined'
console.log(1 + true); // 2
console.log({} + {}); // "[object Object][object Object]"
console.log(newDate(2017, 04, 21) + 1) // "Sun May 21 2017 00:00:00 GMT+0800 (CST)1"

3. ==双等 - 规范11.9.5

规则:

  1. NaN不等于任何值,包括自己;
  2. undefined == null
    1. 这两个值是相等的,但它们各自与其他任何值都不等。
  1. 数字和字符串:
    1. 先把字符串转换成数字,再比较。跟二元加是相反的。1 == Number('1')
  1. 布尔值与其他:
    1. 先把布尔值转换成数字,再比较:Number(true) == xxx
  1. 对象与其他:
    1. 先执行上面情况, 把对象转换成原始值,再比较。
ini 复制代码
// 转换规则:1 == Number('1'),而不是 String(1) == '1'
console.log(1 == '1') // true
// 注意不是 true == Boolean('2'),而是 Number(true) == '2'
console.log(true == '2')	// false

3.1. 一些易错题

  1. console.log([] == ![]) // true
    1. ![]转换成falsefalse转换成0
    2. []转换成'',然后转换成0
    3. 0==0 // true
  1. false==null
    1. null==undefined只有这两个才相等,其他都不等。
  1. '' == [null]'' == [undefined]
    1. 数组的toPrimitive规则决定的[null][undefined]的原始值都是''

4. >, <, >=, <=

规则:

  1. 两边都是字符串,比较的是对应的字符编码值;
    1. '2' > '10' 实际比较的是'2'.charCodeAt() > '10'charCodeAt()
  1. 其他情况都是先转换成数字类型再比较。

5. 其他值转布尔值

除了这些是假值:undefinednullfalse0NaN''

其他都是true

6. 参考文章

相关推荐
酷酷的阿云9 分钟前
不用ECharts!从0到1徒手撸一个Vue3柱状图
前端·javascript·vue.js
aPurpleBerry1 小时前
JS常用数组方法 reduce filter find forEach
javascript
ZL不懂前端2 小时前
Content Security Policy (CSP)
前端·javascript·面试
乐闻x2 小时前
ESLint 使用教程(一):从零配置 ESLint
javascript·eslint
我血条子呢2 小时前
[Vue]防止路由重复跳转
前端·javascript·vue.js
半开半落2 小时前
nuxt3安装pinia报错500[vite-node] [ERR_LOAD_URL]问题解决
前端·javascript·vue.js·nuxt
理想不理想v3 小时前
vue经典前端面试题
前端·javascript·vue.js
小阮的学习笔记3 小时前
Vue3中使用LogicFlow实现简单流程图
javascript·vue.js·流程图
YBN娜3 小时前
Vue实现登录功能
前端·javascript·vue.js