Почему в JavaScript есть [1,2] + [3,4] = "1,23,4"?

Я хотел добавить элементы массива в другой, поэтому я пробовал это:

[1,2] + [3,4]

Он ответил:

"1,23,4"

Что происходит?

Ответ 1

Оператор + не определен для массивов.

Что происходит, так это то, что Javascript преобразует массивы в строки и объединяет их.

 

Update

Поскольку этот вопрос и, следовательно, мой ответ получает много внимания, я почувствовал, что было бы полезно и иметь отношение к обзору о том, как ведет себя оператор + вообще.

Итак, вот оно.

Исключая E4X и специфичные для реализации вещи, Javascript (начиная с ES5) имеет 6 встроенный несколько смутно возвращает object для Null и function для вызываемых объектов, Null на самом деле не является объектом и, строго говоря, в спецификационных реализациях Javascript все функции считаются объектами.

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

Добавляя больше к путанице, объекты-обертки, такие как new Number(5), new Boolean(true) и new String("abc"), являются типами object, а не цифрами, логическими строками или строками, как можно было бы ожидать. Тем не менее для арифметических операторов Number и Boolean ведут себя как числа.

Легко, да? Учитывая все это, мы можем перейти к самому обзору.

Различные типы результатов + по типам операндов

            || undefined | null   | boolean | number | string | object |
=========================================================================
 undefined  || number    | number | number  | number | string | string | 
 null       || number    | number | number  | number | string | string | 
 boolean    || number    | number | number  | number | string | string | 
 number     || number    | number | number  | number | string | string | 
 string     || string    | string | string  | string | string | string | 
 object     || string    | string | string  | string | string | string | 

* применяется к Chrome13, FF6, Opera11 и IE9. Проверка других браузеров и версий остается в качестве упражнения для читателя.

Примечание. Как указано CMS, для определенных случаев объектов, таких как Number, Boolean и пользовательских что оператор + не обязательно выводит строковый результат. Он может варьироваться в зависимости от реализации объекта для примитивного преобразования. Например, var o = { valueOf:function () { return 4; } };, вычисляющий o + 2;, производит 6, a Number, оценивая o + '2', создает '42', a string.

Чтобы узнать, как была создана обзорная таблица, посетите http://jsfiddle.net/1obxuc7m/

Ответ 2

Оператор JavaScript + имеет две цели: добавление двух чисел или объединение двух строк. Он не имеет определенного поведения для массивов, поэтому он преобразует их в строки и затем присоединяет их.

Если вы хотите объединить два массива для создания нового, используйте метод .concat:

[1, 2].concat([3, 4]) // [1, 2, 3, 4]

Если вы хотите эффективно добавлять все элементы из одного массива в другой, вам нужно использовать .push-метод:

var data = [1, 2];

// ES6+:
data.push(...[3, 4]);
// or legacy:
Array.prototype.push.apply(data, [3, 4]);

// data is now [1, 2, 3, 4]

Поведение оператора + определено в ECMA-262 5e Раздел 11.6.1:

11.6.1 Оператор добавления (+)

Оператор сложения выполняет либо конкатенацию строк, либо числовое добавление. Производство AdditiveExpression : AdditiveExpression + MultiplicativeExpression оценивается следующим образом:

  • Пусть lref будет результатом оценки AdditiveExpression.
  • Пусть lval be GetValue(lref).
  • Пусть rref будет результатом оценки MultiplicativeExpression.
  • Пусть rval be GetValue(rref).
  • Пусть lprim be ToPrimitive(lval).
  • Пусть rprim be ToPrimitive(rval).
  • Если Type(lprim) равно String или Type(rprim) is String, тогда
    • Верните строку, которая является результатом объединения ToString(lprim), за которым следует ToString(rprim)
  • Верните результат применения операции добавления к ToNumber(lprim) и ToNumber(rprim). См. Примечание ниже 11.6.3.

Вы можете видеть, что каждый операнд преобразуется ToPrimitive. Читая далее, мы можем обнаружить, что ToPrimitive всегда будет преобразовывать массивы в строки, создавая этот результат.

Ответ 3

Он добавляет два массива , как если бы они были строками.

Строковое представление для первого массива будет "1,2" , а второе будет "3,4" . Поэтому, когда знак + найден, он не может суммировать массивы, а затем объединить их как строки.

Ответ 4

Строки + concats, поэтому он преобразует массивы в строки.

[1,2] + [3,4]
'1,2' + '3,4'
1,23,4

Чтобы объединить массивы, используйте concat.

[1,2].concat([3,4])
[1,2,3,4]

Ответ 5

В JavaScript оператор двоичного сложения (+) выполняет как числовое сложение, так и конкатенацию строк. Однако, когда первый аргумент не является ни числом, ни строкой, он преобразует его в строку (следовательно, "1,2" ), то он делает то же самое со вторым "3,4" и объединяет их с "1,23,4",.

Попробуйте вместо этого использовать "concat" метод массивов:

var a = [1, 2];
var b = [3, 4];
a.concat(b) ; // => [1, 2, 3, 4];

Ответ 6

Преобразование отдельных массивов в строки, а затем объединение строк.

Ответ 7

Похоже, JavaScript превращает ваши массивы в строки и соединяет их вместе. Если вы хотите добавить кортежи вместе, вам придется использовать цикл или функцию карты.

Ответ 8

[1,2]+[3,4] в JavaScript такой же, как и оценка:

new Array( [1,2] ).toString() + new Array( [3,4] ).toString();

и поэтому для решения вашей проблемы лучше всего добавить два массива на месте или без создания нового массива:

var a=[1,2];
var b=[3,4];
a.push.apply(a, b);

Ответ 9

Выполняет именно то, что вы просили.

То, что вы добавляете вместе, это ссылки на массивы (которые JS преобразует в строки), а не числа, как кажется. Это немного напоминает добавление строк вместе: "hello " + "world"= "hello world"

Ответ 10

было бы неплохо, если бы вы могли перегружать операторы в JavaScript, но вы не можете: Могу ли я определить пользовательские перегрузки операторов в Javascript? вы можете только взломать оператор "==", который преобразуется в строки перед сравнением: http://blogger.xs4all.nl/peterned/archive/2009/04/01/462517.aspx

Ответ 11

Это потому, что оператор + предполагает, что операнды являются строками, если они не являются числами. Таким образом, он сначала преобразует их в строку и concats, чтобы дать окончательный результат, если это не число. Кроме того, он не поддерживает массивы.

Ответ 12

Другим результатом с помощью простого знака "+" будет:

[1,2]+','+[3,4] === [1,2,3,4]

Итак, что-то вроде этого должно работать (но!):

var a=[1,2];
var b=[3,4];
a=a+','+b; // [1,2,3,4]

... но он преобразует переменную a из массива в String! Имейте это в виду.

Ответ 13

В некоторых ответах объясняется, как происходит неожиданный нежелательный вывод ('1,23,4'), а некоторые объяснили, как получить ожидаемый желаемый результат ([1,2,3,4]), т.е. конкатенацию массива. Однако характер ожидаемого желаемого результата на самом деле несколько неоднозначен, потому что в исходном вопросе просто говорится: "Я хотел добавить элементы массива в другое...". Это может означать конкатенацию массива, но это также может означать добавление кортежей (например, здесь и здесь), то есть добавление скалярные значения элементов в одном массиве со скалярными значениями соответствующих элементов во втором, например объединение [1,2] и [3,4] для получения [4,6].

Предполагая, что оба массива имеют одну и ту же арность/длину, вот одно простое решение:

const arr1 = [1, 2];
const arr2 = [3, 4];

const add = (a1, a2) => a1.map((e, i) => e + a2[i]);

console.log(add(arr1, arr2)); // ==> [4, 6]