Chciałem dodać elementy tablicy do innego, więc spróbowałem:
[1,2] + [3,4]
Odpowiedział:
"1,23,4"
Co się dzieje?
[5,6,7][1,2]
jest 7
, ponieważ używa ostatni element w drugiej tablicy. Oo
Chciałem dodać elementy tablicy do innego, więc spróbowałem:
[1,2] + [3,4]
Odpowiedział:
"1,23,4"
Co się dzieje?
[5,6,7][1,2]
jest 7
, ponieważ używa ostatni element w drugiej tablicy. Oo
Odpowiedzi:
+
Operator nie jest zdefiniowany dla tablic .
Dzieje się tak, że JavaScript konwertuje tablice na ciągi i łączy je.
Ponieważ na to pytanie i w związku z tym moją odpowiedź zyskuje wiele uwagi, uznałem, że użyteczne i odpowiednie byłoby posiadanie przeglądu tego, jak +
ogólnie zachowuje się operator.
A więc proszę bardzo.
Z wyjątkiem E4X i specyficznych dla implementacji rzeczy, Javascript (od ES5) ma 6 wbudowanych typów danych :
Zwróć uwagę, że chociaż typeof
nieco myląco zwraca wartość object
Null i function
Obiekty, które można wywoływać, Null w rzeczywistości nie jest Obiektem, a ściśle mówiąc, w implementacjach Javascript zgodnych ze specyfikacją wszystkie funkcje są uważane za Obiekty.
Zgadza się - JavaScript nie ma prymitywnych tablic jako takich; tylko instancje obiektu wywoływane Array
z cukrem składniowym w celu złagodzenia bólu.
Dodając do zamieszania, wrapper podmiotów, takich jak new Number(5)
, new Boolean(true)
i new String("abc")
wszystkie są object
typu, a nie liczby, wartości logiczne lub strun, jak można by oczekiwać. Niemniej dla operatorów arytmetycznych Number
i Boolean
zachowywać się jak liczby.
Łatwe, co? Po tym wszystkim możemy przejść do samego przeglądu.
Różne typy wyników +
według typów operandów
|| 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 |
* dotyczy Chrome13, FF6, Opera11 i IE9. Sprawdzanie innych przeglądarek i wersji pozostawia się jako ćwiczenie dla czytelnika.
Uwaga: Jak podkreślił CMS dla pewnych przypadkach obiektów takich jak Number
, Boolean
i niestandardowych te z +
operator nie musi produkować wynik ciąg. Może się różnić w zależności od implementacji konwersji obiektu na pierwotną. Na przykład var o = { valueOf:function () { return 4; } };
oceny o + 2;
produkuje 6
, A number
, oceny o + '2'
produkuje '42'
, A string
.
Aby zobaczyć, jak wygenerowano tabelę przeglądów, odwiedź http://jsfiddle.net/1obxuc7m/
+
Operator JavaScript ma dwa cele: dodanie dwóch liczb lub połączenie dwóch ciągów. Nie ma określonego zachowania dla tablic, więc konwertuje je na ciągi, a następnie łączy je.
Jeśli chcesz dołączyć do dwóch tablic do produkcji nowego, skorzystać z .concat
metody zamiast:
[1, 2].concat([3, 4]) // [1, 2, 3, 4]
Jeśli chcesz efektywnie dodać wszystkie elementy z jednej tablicy do drugiej, musisz użyć metody .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]
Zachowanie +
operatora jest zdefiniowane w ECMA-262 5e sekcja 11.6.1 :
11.6.1 Operator dodawania (+)
Operator dodawania dokonuje konkatenacji łańcucha lub dodawania liczbowego. Produkcja
AdditiveExpression : AdditiveExpression + MultiplicativeExpression
jest oceniana w następujący sposób:
- Pozwól
lref
być wynikiem ocenyAdditiveExpression
.- Niech
lval
będzieGetValue(lref)
.- Pozwól
rref
być wynikiem ocenyMultiplicativeExpression
.- Niech
rval
będzieGetValue(rref)
.- Niech
lprim
będzieToPrimitive(lval)
.- Niech
rprim
będzieToPrimitive(rval)
.- Jeśli
Type(lprim)
jestString
lubType(rprim)
jestString
, to
- Zwraca ciąg będący wynikiem konkatenacji,
ToString(lprim)
po którym następujeToString(rprim)
- Zwróć wynik zastosowania operacji dodawania do
ToNumber(lprim)
iToNumber(rprim)
. Uwaga poniżej 11.6.3.
Widać, że każdy operand jest konwertowany ToPrimitive
. Czytając dalej, możemy przekonać się, że ToPrimitive
zawsze konwertuje tablice na ciągi, wytwarzając ten wynik.
Array.prototype.push.apply(data, [3, 4])
zamiast data.concat([3,4])
?
concat
tworzy nową macierz, dłuższe wywołanie skutecznie rozszerza istniejącą macierz.
[].push.apply(data, [3,4])
dla nieco mniej gadatliwości. Gwarantuje to również, że będzie odporny na zmiany wartości innych osób Array
.
Dodaje dwie tablice, jakby były łańcuchami .
Reprezentacja ciągu dla pierwszej tablicy to „1,2”, a druga to „3,4” . Kiedy więc +
znak zostanie znaleziony, nie może sumować tablic, a następnie konkatenować je jako ciągi znaków.
W +
concats struny, więc przekształca tablic do strun.
[1,2] + [3,4]
'1,2' + '3,4'
1,23,4
Aby połączyć tablice, użyj concat
.
[1,2].concat([3,4])
[1,2,3,4]
W JavaScript operator dodawania binarnego ( +
) wykonuje zarówno dodawanie numeryczne, jak i konkatenację ciągów. Jeśli jednak pierwszym argumentem nie jest ani liczba, ani ciąg, konwertuje go na ciąg (stąd „ 1,2
”), a następnie robi to samo z drugim „ 3,4
” i łączy je w „1,23,4
”.
Zamiast tego spróbuj użyć metody „concat” tablic:
var a = [1, 2];
var b = [3, 4];
a.concat(b) ; // => [1, 2, 3, 4];
Wygląda na to, że JavaScript zamienia tablice w ciągi znaków i łączy je ze sobą. Jeśli chcesz dodać krotki razem, musisz użyć pętli lub funkcji mapy.
[1,2]+[3,4]
w JavaScript to samo, co ocena:
new Array( [1,2] ).toString() + new Array( [3,4] ).toString();
więc aby rozwiązać problem, najlepiej byłoby dodać dwie tablice na miejscu lub bez tworzenia nowej tablicy:
var a=[1,2];
var b=[3,4];
a.push.apply(a, b);
Robi dokładnie to, o co go prosiłeś.
To, co dodajesz razem, to odwołania do tablicy (które JS konwertuje na ciągi), a nie liczby, jak się wydaje. To trochę jak dodawanie ciągów razem: "hello " + "world"
="hello world"
byłoby miło, gdybyś mógł przeciążać operatorów w JavaScript, ale nie możesz: Czy mogę zdefiniować niestandardowe przeciążenia operatorów w JavaScript? możesz tylko zhakować operator „==”, który konwertuje na ciągi przed porównaniem: http://blogger.xs4all.nl/peterned/archive/2009/04/01/462517.aspx
Wynika to z faktu, że operator + zakłada, że operandy są łańcuchami, jeśli nie są liczbami. Najpierw konwertuje je na ciągi znaków i konkataty, aby uzyskać końcowy wynik, jeśli nie jest liczbą. Ponadto nie obsługuje tablic.
Niektóre odpowiedzi wyjaśniają, w jaki sposób '1,23,4'
dzieje się nieoczekiwane niepożądane wyjście ( ), a niektóre wyjaśniają, w jaki sposób uzyskać zakładane oczekiwane wyjście ( [1,2,3,4]
), tj. Konkatenację macierzy. Jednak natura oczekiwanego pożądanego wyniku jest w rzeczywistości nieco niejednoznaczna, ponieważ pierwotne pytanie brzmi po prostu: „Chciałem dodać elementy tablicy do innego ...”. To może oznaczać tablicy konkatenacji ale może również średnią dodanie krotny (np tu i tu ), czyli dodanie skalarne wartości elementów w jednej tablicy do skalarnych wartości odpowiadających im elementów na sekundę, na przykład łączenie [1,2]
i [3,4]
uzyskać [4,6]
.
Zakładając, że obie tablice mają tę samą aryczność / długość, oto jedno proste rozwiązanie:
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]