首页 > 解决方案 > 尝试将符号包装对象显式转换为字符串时出错

问题描述

我在 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它的原型链中有一个返回字符串的函数,因此它应该通过使用该函数来工作。

标签: javascriptlanguage-lawyer

解决方案


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

var sow = Object(Symbol());

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

当您String使用参数调用时value,根据规范

一个。如果 NewTarget 未定义且 Type(value) 为 Symbol,则返回 SymbolDescriptiveString(value)。

湾。让我们成为?ToString(值)。

在这里,由于您将符号包装在对象中,因此它的类型不是符号;相反,它是一个对象,因此ToString被称为。这在使用 object调用时,将首先将对象强制为原语,然后调用ToString它:

  1. 让 primValue 成为 ? ToPrimitive(参数,提示字符串)。
  2. 返回 ?ToString(原始值)。

但是符号不能ToString召唤它们;正如您在同一张表中看到的那样,当传递一个符号时,ToString将抛出一个 TypeError。

这就是为什么String(sow);有效。相反,当您这样做时sow.toString(),您正在使用对象包装符号Symbol.prototype.toString的调用上下文(a )进行调用:this

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

这有点不同。Symbol.prototype.toString从对象中检索底层的 Symbol,然后用 Symbol 调用SymbolDescriptiveString,得到一个带有符号描述值(如果有的话)的字符串。

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

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


推荐阅读