7.5 Symbol 转换成其他原始类型

下面的表格展示了 Symbol 在显示地或者隐式地转换成其他原始类型的时候会发生什么:

转换成 显示转换 隐式转换
boolean Boolean(sym) → OK !sym → OK
number Number(sym) → TypeError sym*2 → TypeError
string String(sym) → OK ''+sym → TypeError
sym.toString() → OK `${sym}` → TypeError

7.5.1 当心:隐式转换成字符串

禁止隐式转换成字符串会很容易导致下面的错误:

const sym = Symbol();

console.log('A symbol: '+sym); // TypeError
console.log(`A symbol: ${sym}`); // TypeError

要修复这些问题,需要显示转换成字符串:

console.log('A symbol: '+String(sym)); // OK
console.log(`A symbol: ${String(sym)}`); // OK

7.5.2 理解隐式转换规则

通常会禁止 Symbol 的隐式转换。本节讲解了为什么会这样。

7.5.2.1 允许真值检查

隐式转换成布尔值是始终可以的,主要用于在 if 语句中检查真值情况以及其他一些场景:

if (value) { ··· }

param = param || 0;

7.5.2.2 意外地将 Symbol 用作属性键

Symbol 是一种特殊的属性键,这就是为什么需要避免意外地将其转换成字符串(字符串是另一种类型的属性键)。在使用一些操作符来计算属性名的时候,这种意外错误就可能发生:

myObject['__' + value]

这就是为啥 value 是 Symbol 的时候会抛出 TypeError 错误。

7.5.2.3 意外地将 Symbol 用作数组索引

你肯定也不期望意外地将 Symbol 用作数组索引。下面的代码展示了当 value 是 Symbol 的时候,这种错误就会发生:

myArray[1 + value]

这就是为什么在这种场景中,该操作会抛出错误。

7.5.3 规范中的显示转换和隐式转换

7.5.3.1 转换成布尔类型

可以使用 Boolean() 显示地将 Symbol 转换成布尔类型。对于 Symbol 类型,会始终返回 true

> const sym = Symbol('hello');
> Boolean(sym)
true

Boolean() 通过内部的 ToBoolean() 操作计算出最终结果。对于 Symbol 和其他真值,该操作返回 true

隐式转换同样使用 ToBoolean()

> !sym
false

7.5.3.2 转换成数值类型

使用 Number() 将 Symbol 显示地转换成数值类型:

> const sym = Symbol('hello');
> Number(sym)
TypeError: can't convert symbol to number

Number() 通过内部的 ToNumber() 操作计算出最终结果,对于 Symbol ,该操作会抛出 TypeError

隐式转换也会使用 [ToNumber()] :

> +sym
TypeError: can't convert symbol to number

7.5.3.3 转换成字符串

使用 String() 将 Symbol 转换成字符串:

> const sym = Symbol('hello');
> String(sym)
'Symbol(hello)'

如果 String() 的参数是 Symbol ,那么该方法会自己将其转换成字符串,然后返回用创建 Symbol 的时候传入的描述字符串(使用 Symbol() 包裹起来)。如果没有提供描述字符串,就会使用空字符串:

> String(Symbol())
'Symbol()'

toString() 方法返回和 String() 相同的结果,但是都不会调用对方,它们都会调用内部的操作 SymbolDescriptiveString()

> Symbol('hello').toString()
'Symbol(hello)'

隐式转换是通过内部的 ToString() 操作来处理的,对于 Symbol ,会抛出 TypeErrorNumber.parseInt() 方法会隐式地将参数转换成字符串:

> Number.parseInt(Symbol())
TypeError: can't convert symbol to string

7.5.3.4 不允许:使用双目加号操作符(+)转换

加号操作符的处理过程是这样的:

  • 将两边的操作数转换成原始类型。
  • 如果某一个操作数是字符串,那么另一个操作数会被隐式转换成字符串(使用 ToString()),然后将它们串联起来,返回结果。
  • 否则,将两个操作数都转换成数值类型,然后相加,返回结果。

隐式转换成字符串和数值都会抛出异常,这意味着不能(直接)将加号运算符用于 Symbol 。

> '' + Symbol()
TypeError: can't convert symbol to string
> 1 + Symbol()
TypeError: can't convert symbol to number

results matching ""

    No results matching ""