Skip to content

Commit 2398898

Browse files
author
yibuyisheng
committed
7.5
1 parent e2c5b8a commit 2398898

File tree

1 file changed

+150
-0
lines changed

1 file changed

+150
-0
lines changed

md/7/7.5.md

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
## 7.5 把 Symbol 转换成其他原始类型
2+
3+
下面的表格展示了 Symbol 在显示地或者隐式地转换成其他原始类型的时候会发生什么:
4+
5+
| 转换成 | 显示转换 | 隐式转换 |
6+
| -- | -- | -- |
7+
| boolean | Boolean(sym) → OK | !sym → OK |
8+
| number | Number(sym) → TypeError | sym*2 → TypeError |
9+
| string | String(sym) → OK | ''+sym → TypeError |
10+
| | sym.toString() → OK | \`${sym}` → TypeError |
11+
12+
### 7.5.1 当心:隐式转换成字符串
13+
14+
禁止隐式转换成字符串会很容易导致下面的错误:
15+
16+
```js
17+
const sym = Symbol();
18+
19+
console.log('A symbol: '+sym); // TypeError
20+
console.log(`A symbol: ${sym}`); // TypeError
21+
```
22+
23+
要修复这些问题,需要显示转换成字符串:
24+
25+
```js
26+
console.log('A symbol: '+String(sym)); // OK
27+
console.log(`A symbol: ${String(sym)}`); // OK
28+
```
29+
30+
### 7.5.2 理解隐式转换规则
31+
32+
通常会禁止 Symbol 的隐式转换。本节讲解了为什么会这样。
33+
34+
#### 7.5.2.1 允许真值检查
35+
36+
隐式转换成布尔值是始终可以的,主要用于在 if 语句中检查真值情况以及其他一些场景:
37+
38+
```js
39+
if (value) { ··· }
40+
41+
param = param || 0;
42+
```
43+
44+
#### 7.5.2.2 意外地将 Symbol 用作属性键
45+
46+
Symbol 是一种特殊的属性键,这就是为什么需要避免意外地将其转换成字符串(字符串是另一种类型的属性键)。在使用一些操作符来计算属性名的时候,这种意外错误就可能发生:
47+
48+
```js
49+
myObject['__' + value]
50+
```
51+
52+
这就是为啥 `value` 是 Symbol 的时候会抛出 `TypeError` 错误。
53+
54+
#### 7.5.2.3 意外地将 Symbol 用作数组索引
55+
56+
你肯定也不期望意外地将 Symbol 用作数组索引。下面的代码展示了当 `value` 是 Symbol 的时候,这种错误就会发生:
57+
58+
```js
59+
myArray[1 + value]
60+
```
61+
62+
这就是为什么在这种场景中,该操作会抛出错误。
63+
64+
### 7.5.3 规范中的显示转换和隐式转换
65+
66+
#### 7.5.3.1 转换成布尔类型
67+
68+
可以使用 [Boolean()](http://www.ecma-international.org/ecma-262/6.0/#sec-boolean-constructor-boolean-value) 显示地将 Symbol 转换成布尔类型。对于 Symbol 类型,会始终返回 `true`
69+
70+
```
71+
> const sym = Symbol('hello');
72+
> Boolean(sym)
73+
true
74+
```
75+
76+
`Boolean()` 通过内部的 [ToBoolean()](http://www.ecma-international.org/ecma-262/6.0/#sec-toboolean) 操作计算出最终结果。对于 Symbol 和其他真值,该操作返回 `true`
77+
78+
隐式转换同样使用 `ToBoolean()`
79+
80+
```
81+
> !sym
82+
false
83+
```
84+
85+
#### 7.5.3.2 转换成数值类型
86+
87+
使用 [Number()](http://www.ecma-international.org/ecma-262/6.0/#sec-number-constructor-number-value) 将 Symbol 显示地转换成数值类型:
88+
89+
```
90+
> const sym = Symbol('hello');
91+
> Number(sym)
92+
TypeError: can't convert symbol to number
93+
```
94+
95+
`Number()` 通过内部的 [ToNumber()](http://www.ecma-international.org/ecma-262/6.0/#sec-tonumber) 操作计算出最终结果,对于 Symbol ,该操作会抛出 `TypeError`
96+
97+
隐式转换也会使用 [ToNumber()]
98+
99+
```
100+
> +sym
101+
TypeError: can't convert symbol to number
102+
```
103+
104+
#### 7.5.3.3 转换成字符串
105+
106+
使用 [String()](http://www.ecma-international.org/ecma-262/6.0/#sec-string-constructor-string-value) 将 Symbol 转换成字符串:
107+
108+
```
109+
> const sym = Symbol('hello');
110+
> String(sym)
111+
'Symbol(hello)'
112+
```
113+
114+
如果 `String()` 的参数是 Symbol ,那么该方法会自己将其转换成字符串,然后返回用创建 Symbol 的时候传入的描述字符串(使用 `Symbol()` 包裹起来)。如果没有提供描述字符串,就会使用空字符串:
115+
116+
```
117+
> String(Symbol())
118+
'Symbol()'
119+
```
120+
121+
`toString()` 方法返回和 `String()` 相同的结果,但是都不会调用对方,它们都会调用内部的操作 [SymbolDescriptiveString()](http://www.ecma-international.org/ecma-262/6.0/#sec-symboldescriptivestring)
122+
123+
```
124+
> Symbol('hello').toString()
125+
'Symbol(hello)'
126+
```
127+
128+
隐式转换是通过内部的 [ToString()](http://www.ecma-international.org/ecma-262/6.0/#sec-tostring) 操作来处理的,对于 Symbol ,会抛出 `TypeError``Number.parseInt()` 方法会隐式地将参数转换成字符串:
129+
130+
```
131+
> Number.parseInt(Symbol())
132+
TypeError: can't convert symbol to string
133+
```
134+
135+
#### 7.5.3.4 不允许:使用双目加号操作符(+)转换
136+
137+
[加号操作符](http://www.ecma-international.org/ecma-262/6.0/#sec-addition-operator-plus)的处理过程是这样的:
138+
139+
- 将两边的操作数转换成原始类型。
140+
- 如果某一个操作数是字符串,那么另一个操作数会被隐式转换成字符串(使用 `ToString()`),然后将它们串联起来,返回结果。
141+
- 否则,将两个操作数都转换成数值类型,然后相加,返回结果。
142+
143+
隐式转换成字符串和数值都会抛出异常,这意味着不能(直接)将加号运算符用于 Symbol 。
144+
145+
```
146+
> '' + Symbol()
147+
TypeError: can't convert symbol to string
148+
> 1 + Symbol()
149+
TypeError: can't convert symbol to number
150+
```

0 commit comments

Comments
 (0)