Я хотів додати елементи масиву в інший, тому спробував це:
[1,2] + [3,4]
Він відповів:
"1,23,4"
Що відбувається?
[5,6,7][1,2]
, 7
оскільки він використовує останній елемент у другому масиві. Oo
Я хотів додати елементи масиву в інший, тому спробував це:
[1,2] + [3,4]
Він відповів:
"1,23,4"
Що відбувається?
[5,6,7][1,2]
, 7
оскільки він використовує останній елемент у другому масиві. Oo
Відповіді:
+
Оператор не визначений для масивів .
Що відбувається, так що Javascript перетворює масиви в рядки і об'єднує їх.
Оскільки це питання, а отже, моя відповідь привертає багато уваги, я вважав, що було б корисно і актуально мати огляд того, як +
поводиться оператор в цілому.
Отже, ось це йде.
За винятком E4X та специфічних для реалізації матеріалів, Javascript (як і ES5) має 6 вбудованих типів даних :
Зауважте, що хоча typeof
дещо заплутано повертається 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]
Поведінка +
оператора визначена у розділі 11.6.1 ECMA-262 5e :
11.6.1 Оператор додавання (+)
Оператор додавання або виконує конкатенацію рядків або числове додавання. Виробництво
AdditiveExpression : AdditiveExpression + MultiplicativeExpression
оцінюється так:
- Дозволяє
lref
буде результат оцінкиAdditiveExpression
.- Дозволяє
lval
будеGetValue(lref)
.- Дозволяє
rref
буде результат оцінкиMultiplicativeExpression
.- Дозволяє
rval
будеGetValue(rref)
.- Дозволяє
lprim
будеToPrimitive(lval)
.- Дозволяє
rprim
будеToPrimitive(rval)
.- Якщо
Type(lprim)
єString
абоType(rprim)
єString
, то
- Поверніть рядок, що є результатом об'єднання,
ToString(lprim)
після чогоToString(rprim)
- Повернути результат застосування операції додавання до
ToNumber(lprim)
таToNumber(rprim)
. Див. Примітку нижче 11.6.3.
Ви можете бачити, що кожен операнд перетворений ToPrimitive
. Читаючи далі, ми можемо виявити, що ToPrimitive
завжди перетворюватиме масиви у рядки, створюючи цей результат.
Array.prototype.push.apply(data, [3, 4])
замість data.concat([3,4])
?
concat
створює новий масив, тим довший виклик ефективно розширює існуючий масив.
[].push.apply(data, [3,4])
для дещо меншої багатослівності. Крім того, це гарантовано стійкість до інших людей, що змінюють цінність Array
.
Він додає два масиви так, ніби вони є рядками .
Представлення рядків для першого масиву буде "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
Це тому, що, + оператор припускає, що операнди є рядковими, якщо вони не є числами. Отже, він спочатку перетворює їх у рядки та конмати, щоб дати кінцевий результат, якщо його не число. Крім того, він не підтримує масиви.
Деякі відповіді тут пояснювали, як відбувається несподіваний небажаний вихід ( '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]
Іншим результатом із використанням простого знака "+" буде:
[1,2]+','+[3,4] === [1,2,3,4]
Отже, щось подібне повинно працювати (але!):
var a=[1,2];
var b=[3,4];
a=a+','+b; // [1,2,3,4]
... але вона перетворить змінну змінної з масиву в рядок! Майте це на увазі.