+ 运算符和类型转换


起因是在别人代码里看到了 +变量名 这样的写法,意思是 “string 转 number"。查资料过程中复习到了类型转换的相关知识,整理一下。

一元运算符的 +

查询 MDN 可以知道,+ 是可以作为一元运算符使用的。用在操作数前面,作用是将操作数转换为 number,转换规则与 Number() 完全相同:(来自 MDN,对应 ECMA 262

可以将字符串转换成整数和浮点数形式
也可以转换非字符值 truefalsenull
小数和十六进制格式字符串也可以转换成数值
负数形式字符串也可以转换成数值(对于十六进制不适用)
如果它不能解析一个值,则计算结果为 NaN

二元运算符的 +

而作为我们熟知的二元 +,规则其实非常简单:

  • 数字和数字相加
  • 字符串和字符串相加

所有其他类型的值都会被隐式转换为这两种类型的值。+ 会触发的类型转换有三种:

  • 转换为原始值 ToPrimitive()
  • 转换为数字 ToNumber()
  • 转换为字符串 ToString()

这三种都是 JavaScript 引擎内部的抽象操作,下面根据 ECMA 262 对这三种方法进行描述:

ToPrimitive

ToPrimitive ( input [ , PreferredType ] )

ToPrimitive 方法具有一个可选的 PreferredType 参数,可以传入转换时的“偏好”,具体而言,传入 NumberString 会分别对应下面的操作:

  1. 如果 input 是个原始值,直接返回
  2. 否则,如果 input 是个对象
    • 如果 PreferredTypeNumber,则按 obj.valueOf() -> obj.toString() 的顺序调用
    • 如果 PreferredTypeString,则按 obj.toString() -> obj.valueOf() 的顺序调用
    • 途中遇到返回原始值就返回,如果一直到最后都没有返回原始值则抛出 TypeError

如果没有传入 PreferredType 时,Date 对象会设为 String,其他对象都会设为 Number

ToNumber

Argument TypeResult
UndefinedNaN
Null+0
Booleamtrue -> 1; false -> +0
Number无需转换
String试着由字符串解析为数字
Symbol / BigIntTypeError
ObjectToPrimitive(input, Number)

这也正是 Number() 作为一个函数调用时引擎内部的操作。

ToString

Argument TypeResult
Undefined"undefined"
Null"null"
Booleamtrue -> "true"; false -> "false"
NumberNumber::toString(input)
String无需转换
SymbolTypeError
BigIntBigInt::toString(input)
ObjectToPrimitive(input, String)

可以通过自己定义对象里的 valueOftoString 来观察引擎内部的操作,这里就不赘述。

二元 + 做了什么

对于操作 value1 + value2,内部其实进行了如下操作:

  1. 试着进行 prim1 / 2 = ToPrimitive(value1 / value2),不传递 PreferredType 进去采用默认操作
  2. 如果上述转换结果 prim 中任意一个为字符串,则把另一个也转为字符串,然后返回两个字符串拼接的结果
  3. 否则,将两个 prim 都转换为数字,返回它们的和

一些实例

[] + [] // -> ''

首先 ToPrimitive:array 的 valueOf 返回它本身;因此继续到 toString,返回空字符串
因此实际上是两个空字符串连接

[] + {} // -> '[object Object]`

因为空对象 toString 会得到 "[object Object]"

{} + {} // -> NaN

这个问题的原因是,js 把第一个大括号对解释成了一个空代码块并忽略了它,实际上执行的是 + {} 也就是 Number({})
关于为什么会解析为代码块可以参考 这个解释

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值