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)hint 为 String:

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

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

2)hint 为 Number:

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

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

3)hint 为空:

如果 input 为 Date 类型,则 hint 为 String,否则 hint 为 Number。

分析 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