隐式类型转换

先抛出简单结论

  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. 参考文章

相关推荐
一路向前的月光2 小时前
Vue2中的监听和计算属性的区别
前端·javascript·vue.js
长路 ㅤ   2 小时前
vue-live2d看板娘集成方案设计使用教程
前端·javascript·vue.js·live2d
Fan_web2 小时前
jQuery——事件委托
开发语言·前端·javascript·css·jquery
Jiaberrr3 小时前
Element UI教程:如何将Radio单选框的圆框改为方框
前端·javascript·vue.js·ui·elementui
安冬的码畜日常5 小时前
【D3.js in Action 3 精译_029】3.5 给 D3 条形图加注图表标签(上)
开发语言·前端·javascript·信息可视化·数据可视化·d3.js
太阳花ˉ5 小时前
html+css+js实现step进度条效果
javascript·css·html
john_hjy6 小时前
11. 异步编程
运维·服务器·javascript
风清扬_jd6 小时前
Chromium 中JavaScript Fetch API接口c++代码实现(二)
javascript·c++·chrome
yanlele6 小时前
前瞻 - 盘点 ES2025 已经定稿的语法规范
前端·javascript·代码规范