为啥隐式符号到字符串的转换会导致 JavaScript 中的 TypeError?

Posted

技术标签:

【中文标题】为啥隐式符号到字符串的转换会导致 JavaScript 中的 TypeError?【英文标题】:Why does implicit Symbol to String conversion' lead to TypeError in JavaScript?为什么隐式符号到字符串的转换会导致 JavaScript 中的 TypeError? 【发布时间】:2017-04-18 02:06:45 【问题描述】:

在 ES6 中 Symbol 上有一个 .toString(),它返回 Symbol 的字符串表示形式,但想知道为什么 '' + Symbol() 不起作用(运行此表达式会抛出我没想到的 TypeError )?后者是否只是在新的Symbol 上调用.toString() 并将其附加(+)到空字符串?

【问题讨论】:

@Dai '' + 123 可以作为隐式类型转换,但为什么'' + Symbol() 甚至不能被视为隐式转换? 对不起,我看错了你的问题。您实际看到的是什么行为?你有TypeError 或其他的吗? @Dai,很抱歉这个问题引起了混乱。稍作修改。我看到'' + Symbol() 抛出 TypeError,想知道为什么会这样,因为Symbol().toString() 有效。 当我尝试 Symbol().__proto__.toString() 时它会抛出一个错误,也许它可以帮助理解这一点......(我不知道答案......) 相关:esdiscuss.org/topic/string-symbol 【参考方案1】:

后者是否只是在新的Symbol 上调用.toString() 并将其附加(+)到空字符串?

实际上不,符号不能隐式转换为字符串或数字,但有趣的是,您可以将它们隐式转换为布尔值。

MDN actually has a section 关于其中一些陷阱:

符号类型转换

处理符号类型转换时的一些注意事项。

尝试将符号转换为数字时,将抛出 TypeError(例如 +symsym | 0)。 当使用松散相等时,Object(sym) == sym 返回true. Symbol("foo") + "bar" 抛出 TypeError (无法将符号转换为字符串)。例如,这可以防止您从符号静默创建新的字符串属性名称。 “更安全”的String(sym) 转换类似于使用符号调用Symbol.prototype.toString(),但请注意new String(sym) 会抛出异常。

此行为记录在 abstract ToString operation 下的规范中:

参数类型:符号

结果:抛出TypeError异常。

abstract ToNumber operation 也是如此:

参数类型:符号

结果:抛出TypeError异常。

要将Symbol 转换为没有TypeError 的字符串,您必须使用toString 方法或String()

【讨论】:

隐式将对象转换为字符串是否意味着在对象上调用Object.prototype.toString() @Thomson 是的,将对象隐式转换为字符串将调用 toString 方法,如果已设置,则在实例本身上或从原型中调用。 作为您的评论,将 Symbol 隐式转换为 String 应该会成功,因为在 Symbol 实例 (Symbol()) 上有一个可行的 toString() @Thomson Symbol 实际上不是 Object 的,它们是原语,它们被明确设计为抛出 TypeError 而不是隐式调用 toString 方法。 @AlexanderO'Mara,他在问当您执行 symbol.toString() 时是否会发生意外的装箱? 或者您应该使用 String(symbol) 来防止装箱吗?跨度> 【参考方案2】:

来自https://developer.mozilla.org/en-US/docs/Web/javascript/Reference/Global_Objects/Symbol/toString。

Symbol 对象覆盖了 Object 对象的 toString 方法; 它不继承 Object.prototype.toString()。对于符号对象, toString 方法返回对象的字符串表示形式。

【讨论】:

这不能回答问题,这就是为什么'' + symbol 不起作用。

以上是关于为啥隐式符号到字符串的转换会导致 JavaScript 中的 TypeError?的主要内容,如果未能解决你的问题,请参考以下文章

符号:隐式字符串转换在 JavaScript 中是如何工作的?

重置设计 rails 的密码会导致“没有将数组隐式转换为字符串”错误

为啥Java在使用“加号”运算符时会执行从双精度到整数的隐式类型转换? [复制]

为啥“as”运算符在 C# 中不使用隐式转换运算符?

为啥 GCC 会警告这种隐式转换?

关于MySQL隐式转换