尝试将符号包装器对象显式转换为字符串时出错

Error when trying to explicitly convert symbol wrapper object to string

我在 firefox web 控制台中尝试了以下内容。

    var sow = (function(){ return this; }).call(Symbol());

    console.log(typeof (sow)); // object

    console.log(sow.toString()); // Works: Symbol()

    String(sow); // Does not work: Throws "TypeError: can't convert symbol to string"

由于某些奇怪的原因,最后一条语句中的显式转换不起作用(抛出错误)。

为什么会这样?

请注意 sow 是一个对象,它有一个 toString 函数返回其原型链中的一个字符串,因此它应该可以通过使用该函数来工作。

首先请注意,您对 sow 的定义可以简化为:

var sow = Object(Symbol());

在草率模式下,它与您的代码执行相同的操作。

当您使用参数 value 调用 String 时,根据 the specification:

a. If NewTarget is undefined and Type(value) is Symbol, return SymbolDescriptiveString(value).

b. Let s be ? ToString(value).

在这里,由于您将符号包装在一个对象中,因此它的类型是而不是一个符号;相反,它是一个对象,所以 ToString 被调用。这在调用 with an object 时将首先将对象强制转换为原始对象,然后对其调用 ToString

  1. Let primValue be ? ToPrimitive(argument, hint String).
  2. Return ? ToString(primValue).

但是不能对符号调用 ToString;正如您在同一个 table 中看到的那样,当传递一个 Symbol 时,ToString 将抛出一个 TypeError。

这就是 String(sow); 起作用的原因。相反,当您执行 sow.toString() 时,您是在使用对象包装符号的调用上下文(this)调用 Symbol.prototype.toString

var sow = Object(Symbol());
console.log(sow.toString === Symbol.prototype.toString);

这有些不同。 Symbol.prototype.toString retrieves the underlying Symbol from the object, and then calls SymbolDescriptiveString 与符号,产生一个带有符号描述值(如果有)的字符串。

请注意,包装在对象中的本机符号 not 在传递给 String 时会 not 抛出,因为 [=当参数是符号时,31=] 将 不会 调用有问题的 ToString 抽象方法。

const sym = Symbol();
console.log(String(sym));
console.log(sym.toString());