1

Проводя некоторые тесты наткнулся на интересное поведение, которое не могу себе объяснить.

Код:

var a = {
  toString: function(){return "It's a string"},
  valueOf: function(){return 100}
};
console.log(a); /// Выводит объект (1)
console.log(+a); /// Выводит 100 в числовом типе (2)
console.log(""+a); /// Выводит "100" в строковом типе (3)
console.log(String(a)); /// Выводит "It's a string" (4)

А теперь по порядку:

  1. Под (1) все понятно - должно вывести объект т.к console.log это и делает если ей дают объект.
  2. Под (2) cудя по преобразованию типов должно быть числовое преобразование и поэтому должен использоваться valueOf.
  3. Под (3) судя по преобразованию типов должно быть строковое преобразование и поэтому должно использоваться toString, но используется valueOf. Почему?
  4. Под (4) используется конструктор для преобразования объекта и поэтому срабатывает toString.

Вопросы:

Что не так с пунктом 3? Какие ньюансы возникают, что интерпретатор так работает?

P.S Если я где-то не прав, поправьте.

Grundy
  • 81,538
MaximPro
  • 3,913
  • 1
    на сколько я помню для приведения к примитиву обьект кастится сначала методом valueOf, тоесть в пункте 3 сначала привели к примитиву, получили 100 , а так как сложение идет со строкой, 100 привели к строке и сложили. – Rostyslav Kuzmovych Aug 20 '17 at 14:39
  • 1
    @RostyslavKuzmovych Если бы сначала всегда использовался valueOf - тогда в 4 примере мы получили бы "100". –  Aug 20 '17 at 15:23
  • @RostyslavKuzmovych не совсем так на learn.javascript написано по-другому. То есть там сказано что будет использоваться тот или иной метод в зависимости от контекста. – MaximPro Aug 20 '17 at 15:24
  • В дубликате описан процесс выбора: в каком случае какой метод должен выбираться – Grundy Aug 20 '17 at 17:06
  • @Grundy довольно непонятен тот алгоритм, нечеловеческим языком написан – MaximPro Aug 20 '17 at 17:08
  • @MaximPro, потому что это псевдокод :) добавил еще один вопрос, как раз с оператором +, по ссылке на спецификацию можешь проследить что и как вызывается – Grundy Aug 20 '17 at 17:08
  • В двух словах. к обоим операндам применяется ToPrimitive, который без дополнительных параметров приводит к number, отсюда для второго параметра, который в данном случае переменная a - будет вызван valueOf – Grundy Aug 20 '17 at 17:11
  • @Grundy насколько мне известно все арифметические действия приводят операнды к числу. Но только когда + это особый случай, и я не понимаю это же прямое преобразование к строке, но методом это игнорируется. Я почитал все что вы скинули, ту спецификацию мне не осилить слишком не понятна она для меня, нужно учиться их читать. – MaximPro Aug 20 '17 at 17:34
  • @MaximPro, ты разобрался почему так происходит?,Я читал дубликат, где Grundy ссылался на спецификацию, но я ее не умею читать) – Виталик Черный Sep 15 '18 at 13:27
  • @ВиталикЧерный а придется :) Именно там раскрывается детализированное описание механизма. Если говорить вкратце про 3ий пример то там срабатывает алгоритм сложения 2 ух операндов. Но а чтобы их сложить нужно привести их к примитивам, и только после сложить. Алгоритм сложения примитивов описан в спецификации. И насчет toString и valueOf в спецификации есть описание этих методов. Но скажу опять вкратце в большинстве случаев используется valueOf. Более подробно нужно читать спецификацию (И то это я вам по памяти рассказал не заглядывая). – MaximPro Sep 16 '18 at 14:49
  • @ВиталикЧерный Впринципе можно было бы подробно расписать алгоритм на пальцах, но это очень долго. Попробуйте почитать спецификацию. Поначалу будет сложно, но после привыкнете. – MaximPro Sep 16 '18 at 14:51
  • @MaximPro спасибо – Виталик Черный Sep 17 '18 at 21:06

1 Answers1

0

Вопрос о конкатенации решается уже после преобразования обоих операндов в примитивы. Т.е. сначала происходит численное преобразование объекта (т.к. + это математический оператор), а уже потом строковое (т.к. второй операнд строка).

  • Спорный момент. Поясню. Преобразование к числу: +a или Number(a). Преобразование к строке: "" + a или String(a). Это кстати написано learn.javascript. – MaximPro Aug 20 '17 at 16:06
  • И кстати когда идет преобразование к числу используется унарный оператор сложения. А вот когда + стоит в контексте сложения двух операндов тут стоит призадуматься. – MaximPro Aug 20 '17 at 16:08
  • Да нет тут спорного момента. –  Aug 20 '17 at 16:41