JavaScript 基础 - 从加法运算符说到类型转换

从 加法运算符 说到 类型转换

What is {} + {} in JavaScript? 译文 JavaScript中, {} + {} 等于多少? 说起:

1,先做个简单的测试

1
2
3
4
5
6
[] + []   // ""
[] + {} // "[object Object]"
{} + [] // 0
({} + []) // "[object Object]"
{} + {} // NaN 或者 "[object Object][object Object]"
({} + {}) // "[object Object][object Object]"

2,javaScript 中的加法运算符

官方文档:(ECMA-262) The Addition operator ( + )

AdditiveExpression : AdditiveExpression + MultiplicativeExpression

前戏:

JavaScript中的值分为原始值( primitives )和对象值( objects )。

原始值包括了 String,Number,Boolean,Null,Undefined。

对象值包括了 Array,Object,Function,RegExp,Date。

转换步骤:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 1,对 AdditiveExpression 求值,存入 lref。
var lref = AdditiveExpression;

// 2,对 lref 的值,进行 GetValue 取值操作,判断 lref 的类型,再使用对应的取值方法。
// 具体查看:http://ecma-international.org/ecma-262/5.1/#sec-8.7.1
var lval = GetValue(lref);

// 3,同 1。
var rref = MultiplicativeExpression;

// 4,同 2。
var rval = GetValue(rref);

// 5,对 lval 的值,进行 ToPrimitive 原始值的转换操作。
// 具体查看:http://ecma-international.org/ecma-262/5.1/#sec-9.1
var lprim = ToPrimitive(lval);

// 6,同 5。
var rprim = ToPrimitive(rval);
// 7,判断 lprim 和 rprim 的类型,只要有一个是 String 类型,就都转化为 String 类型,否则就都转化为 Number 类型。
if(Type(lprim) === 'String' || Type(rprim) === 'String') {
ToString(lprim);
ToString(rprim);
} else {
ToNumber(lprim);
ToNumber(rprim);
}

分析 ToPrimitive() 方法:

语法: ToPrimitive(input [, PreferredType])

PreferredType 为可选可以,可以是 Number 或者 String

1,如果参数为原始值,返回参数本身。

2,如果参数为对象,调用内部方法 DefaultValue(hint)

DefaultValue(hint) 方法中,hint 接收 PreferredType 传入的值,三种情况

1)hintString

先调用 toString() 方法,值为原始值则返回该值,

再调用 valueOf() 方法,值为原始值则返回该值,不是,则抛出 TypeError 异常。

2)hintNumber

先调用 valueOf() 方法,值为原始值则返回该值,

再调用 toString() 方法,值为原始值则返回该值,不是,则抛出 TypeError 异常。

3)hint 为空:

如果 inputDate 类型,则 hintString,否则 hintNumber

分析 ToNumber() 方法:

ToNumber() 的转换规则

参数类型 结果
Undefined NaN
Null +0
Boolean true 转换为 1。false 转换为 +0.
Number 不转换。
String 根据字符串类型的转换规则。(ToNumber Applied to the String Type
Object 先调用 ToPrimitive(input, Number) 转换成原始值,再调用 ToNumber(input)

分析 ToString() 方法:

参数类型 结果
Undefined “undefined”
Null “null”
Boolean true 转换为 “true”,false 转换为 “false”。
Number 根据数值类型的转换规则。(ToString Applied to the Number Type
String 不转换。
Object 先调用 ToPrimitive(input, String) 转换成原始值,再调用 ToString(input)

意外:

1
2
3
4
{} + {}		// NaN 或者 "[object Object][object Object]"
({} + {}) // "[object Object][object Object]"
{} + [] // 0
({} + []) // "[object Object]"

部分浏览器会把 {} 解析为空代码块并忽略掉,所以这里的 + 就变成了一元运算符
其实就是调用了 ToNumber(GetValue(expr)) 方法。

参考:

运算符:

What is {} + {} in JavaScript?

JavaScript中, {} + {} 等于多少?

Fake operator overloading in JavaScript

Improving the JavaScript typeof operator

What is JavaScript’s typeof operator used for?

对象:

JavaScript: converting any value to an object

JavaScript values: not everything is an object