Согласно Флэнагану (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());