Ошибка при попытке явно преобразовать объект-оболочку символа в строку - PullRequest
4 голосов
/ 11 марта 2020

Я попробовал следующее в firefox веб-консоли.

    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, возвращающую строку в цепочке прототипов, поэтому он должен работать с использованием этого функция.

1 Ответ

3 голосов
/ 11 марта 2020

Во-первых, обратите внимание, что ваше определение sow может быть упрощено до:

var sow = Object(Symbol());

, что делает то же самое, что и ваш код в небрежном режиме.

Когда вы звоните String с аргументом value, для спецификации :

a. Если NewTarget не определено и Type (значение) равно Symbol, вернуть SymbolDescriptiveString (значение).

b. Давай будем ? ToString (значение).

Здесь, поскольку вы завернули символ в объект, его тип равен , а не символ; скорее это объект, так что ToString называется. Это, когда вызывается с объектом , сначала приведет объект к примитиву, затем вызовет ToString для него:

  1. Пусть primValue будет? ToPrimitive (аргумент, строка подсказки).
  2. Возврат? ToString (primValue).

Но для символов не может быть вызвано ToString; как вы можете видеть в той же таблице, когда передано Symbol, ToString сгенерирует ошибку TypeError.

Вот почему String(sow); работает. Напротив, когда вы делаете sow.toString(), вы вызываете Symbol.prototype.toString с вызывающим контекстом (this) обернутого объекта символа:

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

Что делает что-то несколько другое. Symbol.prototype.toString получает базовый Symbol из объекта и затем вызывает SymbolDescriptiveString с Symbol, в результате чего получается строка с описательным значением символа (если есть).

Обратите внимание, что нативный символ , а не , обернутый в объект, не выбрасывает при передаче на String, потому что String конструктор будет не вызовите проблемный c ToString абстрактный метод, когда аргумент является символом.

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