0

Как видно из примера ниже, массив и число складываются как строки.

console.log([5] + 25); //525

Почему так происходит? При выполнении сложения для массива запускается метод toString? Разве метод toString не должен запускаться только при попытке преобразования объекта к строке (String, alert...)? А в этом случае я не пытаюсь преобразовать массив к строке...

yar85
  • 10,940
Eva
  • 1,889
  • 8
  • 26
  • 3
    А что вы пытаетесь сделать? – Эникейщик Sep 10 '21 at 18:42
  • 2
    Поскольку оператор сложения используется и для конкатенации строк, интерпретатор не может быть уверен, что вы не хотите его так использовать. Подробнее см. https://learn.javascript.ru/object-toprimitive – vsemozhebuty Sep 10 '21 at 18:43
  • 1
    а у массивов нет toString? – highpassion Sep 10 '21 at 18:55

1 Answers1

6

Согласно Флэнагану (JavaScript. Полное руководство, 7-е издание - 2021):

Операция + в JavaScript выполняет сложение чисел и конкатенацию строк. Если любой из ее операндов оказывается объектом, то интерпретатор JavaScript преобразует его в элементарное значение с применением алгоритма no-preference. После получения двух элементарных значений проверяются их типы. Если один из аргументов является строкой, тогда другой преобразовывается в строку и выполняется конкатенация строк.

То есть, массив преобразуется в строку, почему:

Алгоритм no-preference зависит от класса преобразуемого объекта. Если объект относится к классу Date, тогда интерпретатор JavaScript применяет алгоритм prefer-string. Для любого другого объекта интерпретатор JavaScript использует агоритм prefer-number.

Алгоритм prefer-number первым испытывает valueOf(), а вторым - toString().

(Если valueOf() не существует или возвращает объект). Другими словами, массив должен бы преобразоваться в число, НО:

Класс Array наследует стандартный метод valueOf(), который не возвращает элементарное значение. Таким образом, когда мы пытаемся преобразовать массив в число, то в итоге получаем вызов метода toString() массива.

Массив с единственным элементом преобразуется в ту же строку, что и этот один элемент. Если массив содержит единственное число, то оно преобразуется в строку.

Таким образом, массив, в силу того, что его метод valueOf() возвращает сам массив как объект, в итоге возвращает результат вызова toString().

Для эксперимента можно переписать метод valueOf():

Array.prototype.valueOf = function(){
    return Number(this[0]);
}
console.log([5] + 25);

То, что возвращает родной valueOf() для сравнения:

console.log([5].valueOf());
Leonid
  • 5,797