Dlaczego jest [1,2] + [3,4] = "1,23,4" w JavaScript?
Chciałem dodać elementy tablicy do innej, więc próbowałem tego:
[1,2] + [3,4]
Odpowiedziało:
"1,23,4"
Co się dzieje? 13 answers
Operator +
nie jest zdefiniowany dla tablic.
Dzieje się tak, że Javascript konwertuje tablice na ciągi znaków i łączy je.
Update
Ponieważ to pytanie i w związku z tym moja odpowiedź jest coraz dużo uwagi, uznałem, że byłoby przydatne i istotne, aby mieć przegląd o tym, jak operator +
zachowuje się ogólnie.
Z wyłączeniem E4X i specyficznych dla implementacji rzeczy, Javascript (od ES5) ma 6 wbudowane typy danych :
- Undefined
- Null
- Boolean
- Liczba
- String
- obiekt
Zauważ, że chociaż typeof
nieco mylnie powraca object
dla obiektów null i function
, Null nie jest w rzeczywistości obiektem i ściśle mówiąc, w implementacjach Javascript zgodnych ze specyfikacją wszystkie funkcje są uważane za przedmioty.
To prawda - Javascript nie ma żadnych prymitywnych tablic jako takich; tylko instancje obiektu o nazwie Array
z odrobiną cukru składniowego, aby złagodzić ból.
Dodając więcej do zamieszania, encje wrappera, takie jak new Number(5)
, new Boolean(true)
i {[9] } to wszystkie typy object
, a nie liczby, booleany lub łańcuchy, jak można się spodziewać. Niemniej jednak operatory arytmetyczne Number
i Boolean
zachowują się jak liczby.
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 jest pozostawione jako ćwiczenie dla czytelnika.
Uwaga: jak wskazuje CMS , dla niektórych przypadków obiektów takich jak Number
, Boolean
i niestandardowe operator +
niekoniecznie generuje wynik Łańcuchowy. Może się różnić w zależności od implementacja obiektu do prymitywnej konwersji. Na przykład var o = { valueOf:function () { return 4; } };
ocena o + 2;
produkuje 6
, a number
, ocena o + '2'
produkuje '42'
, a string
.
Aby zobaczyć, jak wygenerowano tabelę przeglądową, odwiedź stronę http://jsfiddle.net/1obxuc7m/
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:50
Operator JavaScript +
ma dwa cele: dodawanie dwóch liczb lub łączenie dwóch łańcuchów. Nie ma specyficznego zachowania dla tablic, więc konwertuje je na łańcuchy, a następnie je łączy.
Jeśli chcesz połączyć dwie tablice, aby utworzyć nową, użyj .concat
metody :
[1, 2].concat([3, 4]) // [1, 2, 3, 4]
Jeśli chcesz efektywnie dodawać wszystkie elementy z jednej tablicy do drugiej, musisz użyć the .metoda 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 +
operator jest zdefiniowany w sekcji ECMA-262 5e 11.6.1:
11.6.1 operator dodawania ( + )
Operator dodawania wykonuje konkatenację łańcuchową lub dodawanie liczbowe. Produkcja
AdditiveExpression : AdditiveExpression + MultiplicativeExpression
jest oceniana w następujący sposób:
- niech
lref
będzie wynikiem ocenyAdditiveExpression
.- niech
lval
będzieGetValue(lref)
.- niech {[10] } będzie wynikiem oceny
MultiplicativeExpression
.- niech
rval
będzieGetValue(rref)
.- niech
lprim
będzieToPrimitive(lval)
.- niech
rprim
będzieToPrimitive(rval)
.- If
Type(lprim)
isString
orType(rprim)
isString
, then
- zwraca łańcuch będący wynikiem połączenia
ToString(lprim)
, po którym następujeToString(rprim)
- zwraca wynik zastosowania operacji dodawania do
ToNumber(lprim)
iToNumber(rprim)
. Zob. Uwaga poniżej 11.6.3.
Widać, że każdy operand jest konwertowany ToPrimitive
. Czytając dalej możemy stwierdzić, że ToPrimitive
będzie zawsze konwertować tablice na ciągi znaków, uzyskanie tego wyniku.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-15 08:55:23
Dodaje dwie tablice tak, jakby były łańcuchami.
Reprezentacja łańcuchowa dla pierwszej tablicy będzie "1,2" a drugi byłby "3,4". Tak więc po znalezieniu znaku +
, nie może on sumować tablic, a następnie łączyć ich jako ciągi znaków.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-19 17:09:30
+
łączy łańcuchy, więc konwertuje tablice na łańcuchy.
[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]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-19 16:58:50
W JavaScript operator dodawania binarnego (+
) wykonuje zarówno dodawanie liczbowe, jak i konkatenację łańcuchów. Jeśli jednak pierwszy argument nie jest ani liczbą, ani łańcuchem, to przekształca go w łańcuch (stąd "1,2
"), to robi to samo z drugim "3,4
" i łączy je z "1,23,4
".
Spróbuj użyć zamiast tego metody" concat " tablic:
var a = [1, 2];
var b = [3, 4];
a.concat(b) ; // => [1, 2, 3, 4];
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-19 17:00:30
Konwertuje poszczególne tablice na ciągi znaków, a następnie łączy je.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-19 16:57:29
Wygląda na to, że JavaScript zamienia twoje 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.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-19 16:57:28
[1,2]+[3,4]
w JavaScript jest to samo co ewaluacja:
new Array( [1,2] ).toString() + new Array( [3,4] ).toString();
I tak, aby rozwiązać problem, najlepiej byłoby dodać dwie tablice w miejscu lub bez tworzenia nowej tablicy:
var a=[1,2];
var b=[3,4];
a.push.apply(a, b);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-27 01:58:42
Robi dokładnie to, o co prosiłeś.
To, co dodajesz, to odwołania do tablic (które js konwertuje na ciągi znaków), a nie liczby, jak się wydaje. To trochę jak dodawanie ciągów razem: "hello " + "world"
= "hello world"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-19 16:57:03
Byłoby miło, gdybyś mógł przeciążać operatory w JavaScript, ale nie możesz: Czy Mogę zdefiniować własne przeciążenia operatorów w Javascript? możesz zhakować tylko operator"==", który konwertuje na ciągi przed porównaniem: http://blogger.xs4all.nl/peterned/archive/2009/04/01/462517.aspx
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:02
Jest tak dlatego, że operator + zakłada, że operatory są łańcuchami, jeśli nie są liczbami. Tak więc najpierw konwertuje je na ciąg i konkatedry, aby dać końcowy wynik, jeśli nie jest liczbą. Ponadto nie obsługuje tablic.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-20 11:06:17
Kolejny wynik przy użyciu zwykłego znaku " + " będzie następujący:
[1,2]+','+[3,4] === [1,2,3,4]
Więc coś takiego powinno działać (ale!):
var a=[1,2];
var b=[3,4];
a=a+','+b; // [1,2,3,4]
... ale to przekonwertuje zmienną a Z Tablicy na ciąg znaków! Pamiętaj o tym.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-12 09:07:48
Niektóre odpowiedzi wyjaśniły, jak dzieje się nieoczekiwane niepożądane wyjście ('1,23,4'
), a niektóre wyjaśniły, jak uzyskać to, co zakładają, że jest oczekiwanym pożądanym wyjściem ([1,2,3,4]
), tj. konkatenację tablicy. Jednak charakter oczekiwanego pożądanego wyniku jest w rzeczywistości nieco niejednoznaczny, ponieważ pierwotne pytanie stwierdza po prostu " chciałem dodać elementy tablicy do innej...". Że może oznaczać konkatenację tablicy, ale może również oznaczać dodawanie krotki (np. tutaj i tutaj), tj. dodawanie wartości skalarnych elementów w jednej tablicy do wartości skalarnych odpowiadających im elementów w drugiej, np. łączenie [1,2]
i [3,4]
w celu uzyskania [4,6]
.
Zakładając, że obie tablice mają tę samą arytmetykę / 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]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:07