Преобразование объектов в примитивы возвращает, неправильный результат

let user = {
  name: ' Опа',
  age: 100,
  [Symbol.toPrimitive](hint) {
    if (hint == "string") {
      // Выводит {name:Опа}.
      return `{name:${this.name}}`;
    } else {
      // Результат должен быть {age:100} аналогично {name:Опа},
      return `{age:${this.age}}`;
    } // но выходит ошибка. Как решить эту проблему?

  }
};

alert(user);
alert(+user);


Ответы (1 шт):

Автор решения: Grundy

Согласно спецификации оператор унарный + выполняет следующие действия:

  1. Вычисляет значение параметра
  2. Вызывает внутреннюю функцию ToNumber и возвращает ее результат.

Согласно спецификации функция ToNumber выполняет следующие действия:

  1. В случае примитивных типов возвращает результат согласно таблице
  2. В случае объекта
    1. Приводит объект к примитивном значению с помощью внутренней функции ToPrimitive, передавая параметр hint равный number.
    2. Применяет себя же к полученному примитивному значению.

Применяя данный алгоритм к коду в вопросе можно заметить, что

  1. для объекта определена его функция ToPrimitive,
  2. для hint=number эта функция возвращает строку
  3. согласно таблице, возвращенная строка не является числом
  4. результат оператора - NaN

Чтобы получить {age:100} в данном случае, можно воспользоваться оператором +.

При сложении со строкой, примитивное значение второго операнда так же будет приведено к строке:

let user = {
  name: ' Опа',
  age: 100,
  [Symbol.toPrimitive](hint) {
    if (hint == "string") {
      // Выводит {name:Опа}.
      return `{name:${this.name}}`;
    } else {
      // Результат должен быть {age:100} аналогично {name:Опа},
      return `{age:${this.age}}`;
    } // но выходит ошибка. Как решить эту проблему?

  }
};

console.log('' + user);

→ Ссылка