Ah-ha-ha, sadysta przesłuchujący może zapytać nawet coś takiego - co to zwróci [1,2] + [5,6,7] [1,2]. dlaczego?
shabunc
9
Myślę, że [1,2] + [3,4] to najbardziej oceniane wyrażenie w Firebug w tym tygodniu, po alarmie („bzdura”).
okeen
6
Chcesz się pośmiać ? Spróbuj [] + [], {} + [], {} + {} i [] + {}
Intrepidd
1
@shabunc - troska o wyjaśnienie, dlaczego [5,6,7][1,2]jest 7, ponieważ używa ostatni element w drugiej tablicy. Oo
vsync,
Odpowiedzi:
518
+Operator nie jest zdefiniowany dla tablic .
Dzieje się tak, że JavaScript konwertuje tablice na ciągi i łączy je.
Aktualizacja
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 :
Nieokreślony
Zero
Boolean
Numer
Strunowy
Obiekt
Zwróć uwagę, że chociaż typeofnieco myląco zwraca wartośćobject Null i functionObiekty, 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 Arrayz 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ą objecttypu, a nie liczby, wartości logiczne lub strun, jak można by oczekiwać. Niemniej dla operatorów arytmetycznych Numberi Booleanzachowywać 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, Booleani 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.
+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 .concatmetody 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]
Operator dodawania dokonuje konkatenacji łańcucha lub dodawania liczbowego. Produkcja AdditiveExpression : AdditiveExpression + MultiplicativeExpressionjest oceniana w następujący sposób:
Pozwól lrefbyć wynikiem oceny AdditiveExpression.
Niech lvalbędzie GetValue(lref).
Pozwól rrefbyć wynikiem oceny MultiplicativeExpression.
Niech rvalbędzie GetValue(rref).
Niech lprimbędzie ToPrimitive(lval).
Niech rprimbędzie ToPrimitive(rval).
Jeśli Type(lprim)jest Stringlub Type(rprim)jest String, 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)i ToNumber(rprim). Uwaga poniżej 11.6.3.
Widać, że każdy operand jest konwertowany ToPrimitive. Czytając dalej, możemy przekonać się, że ToPrimitivezawsze konwertuje tablice na ciągi, wytwarzając ten wynik.
+1, ponieważ ta odpowiedź nie tylko wyjaśnia problem, ale także wyjaśnia, jak zrobić to dobrze.
schnaader,
3
jest tu trochę tmi, ale zgadzam się ze schnaaderem. Najlepsze odpowiedzi wyjaśniają problem / błąd / zachowanie, o które się pytają, a następnie pokazują, jak uzyskać zamierzony rezultat. +1
matthewdunnam
1
Dlaczego miałbyś używać bardziej szczegółowego Array.prototype.push.apply(data, [3, 4])zamiast data.concat([3,4])?
evilcelery
5
@evilcelery: Służą do różnych celów. concattworzy nową macierz, dłuższe wywołanie skutecznie rozszerza istniejącą macierz.
Jeremy Banks,
1
Możesz użyć [].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.
Sam Tobin-Hochstadt,
43
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.
Tak, to pierwsze i unikalne wyjaśnienie, które przychodzi do głowy, ale czy to nie jest dziwne zachowanie? może jest jakaś mroczna, nieznana operacja / transformacja, a chciałbym poznać wewnętrzne: P
okeen
40
W +concats struny, więc przekształca tablic do strun.
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];
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"
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.
Operator + NIE może zakładać, że operandy są łańcuchami, ponieważ między 1 + 1 == 2. Wynika to z faktu, że „+” nie jest zdefiniowane dla tablic, więc to je ciągnie.
okeen
0
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:
[5,6,7][1,2]
jest7
, ponieważ używa ostatni element w drugiej tablicy. OoOdpowiedzi:
+
Operator nie jest zdefiniowany dla tablic .Dzieje się tak, że JavaScript konwertuje tablice na ciągi i łączy je.
Aktualizacja
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 ifunction
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)
inew String("abc")
wszystkie sąobject
typu, a nie liczby, wartości logiczne lub strun, jak można by oczekiwać. Niemniej dla operatorów arytmetycznychNumber
iBoolean
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* 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ładvar o = { valueOf:function () { return 4; } };
ocenyo + 2;
produkuje6
, Anumber
, ocenyo + '2'
produkuje'42'
, Astring
.Aby zobaczyć, jak wygenerowano tabelę przeglądów, odwiedź http://jsfiddle.net/1obxuc7m/
źródło
+
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:Jeśli chcesz efektywnie dodać wszystkie elementy z jednej tablicy do drugiej, musisz użyć metody .push :
Zachowanie
+
operatora jest zdefiniowane w ECMA-262 5e sekcja 11.6.1 :Widać, że każdy operand jest konwertowany
ToPrimitive
. Czytając dalej, możemy przekonać się, żeToPrimitive
zawsze konwertuje tablice na ciągi, wytwarzając ten wynik.źródło
Array.prototype.push.apply(data, [3, 4])
zamiastdata.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óbArray
.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.źródło
W
+
concats struny, więc przekształca tablic do strun.Aby połączyć tablice, użyj
concat
.źródło
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:
źródło
Konwertuje poszczególne tablice na ciągi, a następnie łączy je.
źródło
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.
źródło
[1,2]+[3,4]
w JavaScript to samo, co ocena:więc aby rozwiązać problem, najlepiej byłoby dodać dwie tablice na miejscu lub bez tworzenia nowej tablicy:
źródło
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"
źródło
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
źródło
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.
źródło
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:
źródło
Kolejnym wynikiem przy użyciu prostego znaku „+” będzie:
Więc coś takiego powinno działać (ale!):
... ale przekształci zmienną a z tablicy na łańcuch! Pamiętaj o tym.
źródło