Я хотел добавить элементы массива в другой, поэтому я пробовал это:
[1,2] + [3,4]
Он ответил:
"1,23,4"
Что происходит?
Я хотел добавить элементы массива в другой, поэтому я пробовал это:
[1,2] + [3,4]
Он ответил:
"1,23,4"
Что происходит?
Оператор +
не определен для массивов.
Что происходит, так это то, что Javascript преобразует массивы в строки и объединяет их.
Поскольку этот вопрос и, следовательно, мой ответ получает много внимания, я почувствовал, что было бы полезно и иметь отношение к обзору о том, как ведет себя оператор +
вообще.
Итак, вот оно.
Исключая 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/
Оператор 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
beGetValue(lref)
.- Пусть
rref
будет результатом оценкиMultiplicativeExpression
.- Пусть
rval
beGetValue(rref)
.- Пусть
lprim
beToPrimitive(lval)
.- Пусть
rprim
beToPrimitive(rval)
.- Если
Type(lprim)
равноString
илиType(rprim)
isString
, тогда
- Верните строку, которая является результатом объединения
ToString(lprim)
, за которым следуетToString(rprim)
- Верните результат применения операции добавления к
ToNumber(lprim)
иToNumber(rprim)
. См. Примечание ниже 11.6.3.
Вы можете видеть, что каждый операнд преобразуется ToPrimitive
. Читая далее, мы можем обнаружить, что ToPrimitive
всегда будет преобразовывать массивы в строки, создавая этот результат.
Он добавляет два массива , как если бы они были строками.
Строковое представление для первого массива будет "1,2" , а второе будет "3,4" . Поэтому, когда знак +
найден, он не может суммировать массивы, а затем объединить их как строки.
Строки +
concats, поэтому он преобразует массивы в строки.
[1,2] + [3,4]
'1,2' + '3,4'
1,23,4
Чтобы объединить массивы, используйте concat
.
[1,2].concat([3,4])
[1,2,3,4]
В JavaScript оператор двоичного сложения (+
) выполняет как числовое сложение, так и конкатенацию строк. Однако, когда первый аргумент не является ни числом, ни строкой, он преобразует его в строку (следовательно, "1,2
" ), то он делает то же самое со вторым "3,4
" и объединяет их с "1,23,4
",.
Попробуйте вместо этого использовать "concat" метод массивов:
var a = [1, 2];
var b = [3, 4];
a.concat(b) ; // => [1, 2, 3, 4];
Преобразование отдельных массивов в строки, а затем объединение строк.
Похоже, JavaScript превращает ваши массивы в строки и соединяет их вместе. Если вы хотите добавить кортежи вместе, вам придется использовать цикл или функцию карты.
[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);
Выполняет именно то, что вы просили.
То, что вы добавляете вместе, это ссылки на массивы (которые JS преобразует в строки), а не числа, как кажется. Это немного напоминает добавление строк вместе: "hello " + "world"
= "hello world"
было бы неплохо, если бы вы могли перегружать операторы в JavaScript, но вы не можете: Могу ли я определить пользовательские перегрузки операторов в Javascript? вы можете только взломать оператор "==", который преобразуется в строки перед сравнением: http://blogger.xs4all.nl/peterned/archive/2009/04/01/462517.aspx
Это потому, что оператор + предполагает, что операнды являются строками, если они не являются числами. Таким образом, он сначала преобразует их в строку и concats, чтобы дать окончательный результат, если это не число. Кроме того, он не поддерживает массивы.
Другим результатом с помощью простого знака "+" будет:
[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! Имейте это в виду.
В некоторых ответах объясняется, как происходит неожиданный нежелательный вывод ('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]