尝试将符号包装器对象显式转换为字符串时出错
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
:
- Let primValue be ? ToPrimitive(argument, hint String).
- 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());
我在 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
:
- Let primValue be ? ToPrimitive(argument, hint String).
- 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());