JavaScript'te neden [1,2] + [3,4] = “1,23,4”?


405

Bir dizinin öğelerini başka birine eklemek istedim, bu yüzden bunu denedim:

[1,2] + [3,4]

Yanıt verdi:

"1,23,4"

Ne oluyor?



29
Ah-ha-ha, sadist görüşmeci bile böyle bir şey sorabilir - bunun ne getireceği [1,2] + [5,6,7] [1,2]. neden?
shabunc

9
Sanırım [1,2] + [3,4] uyarıdan sonra ('bok') bu hafta kundakçıda en çok değerlendirilen ifade oldu.
okeen

6
Gülmek istiyorum ? [] + [], {} + [], {} + {} Ve [] + {}
Intrepidd

1
@shabunc - neden bakım açıklamaya [5,6,7][1,2]olduğu 7ikinci dizideki son öğe kullanması nedeniyle. Oo
vsync

Yanıtlar:


518

+Operatör diziler için tanımlanmamıştır .

Ne olur Javascript dizileri dizelere dönüştürür ve bunları birleştirir.

 

Güncelleme

Bu soru ve sonuç olarak cevabım çok dikkat çektiğinden , operatörün genel olarak nasıl +davrandığına dair bir genel bakışa sahip olmanın yararlı ve alakalı olacağını düşündüm .

Yani, işte gidiyor.

E4X ve uygulamaya özel şeyler hariç, Javascript (ES5'ten itibaren) 6 yerleşik veri türüne sahiptir :

  1. Tanımsız
  2. Boş
  3. Boole
  4. Numara
  5. sicim
  6. Nesne

Null ve çağrılabilir Nesneler için typeof biraz kafa karıştırıcı olsa da , Null aslında bir Nesne değildir ve tam olarak konuşursak, spesifikasyona uygun Javascript uygulamalarında tüm işlevlerin Nesne olarak kabul edildiğini unutmayın.objectfunction

Bu doğru - Javascript'in ilkel dizileri yok ; sadece bir nesnenin Arrayağrıyı hafifletmek için sözdizimsel şekerle çağırdığı durumlar .

Gibi kuruluşlar sarıcı, karışıklığa daha eklenmesi new Number(5), new Boolean(true)ve new String("abc")tümü objecttürü, bir tahmin edebileceğiniz gibi sayılar değil, Boolean veya dizeleri. Yine de aritmetik operatörler Numberve Booleansayı olarak davranırlar.

Kolay, ha? Tüm bunlar yoldan çıktığında, genel görünümün kendisine geçebiliriz.

+Operand türlerine göre farklı sonuç türleri

            || 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 ve IE9 için geçerlidir. Diğer tarayıcıları ve sürümleri kontrol etmek okuyucu için bir alıştırma olarak bırakılmıştır.

Not: CMS tarafından işaret edildiği gibi Number, nesneler Booleanve özel nesneler gibi belirli durumlar için , +operatör mutlaka bir dize sonucu üretmez. Nesnenin ilkel dönüşüme uygulanmasına bağlı olarak değişebilir. Örnek için var o = { valueOf:function () { return 4; } };değerlendirilmesi o + 2;üreten 6bir numberdeğerlendirilmesi o + '2'üreten '42'bir, string.

Genel bakış tablosunun nasıl oluşturulduğunu görmek için http://jsfiddle.net/1obxuc7m/ adresini ziyaret edin.


244

JavaScript'in +operatörünün iki amacı vardır: iki sayı eklemek veya iki dizeye katılmak. Diziler için belirli bir davranışı yoktur, bu nedenle bunları dizelere dönüştürür ve sonra birleştirir.

Yenisini üretmek için iki diziyi katılmak istiyorsanız, kullanmak yöntemi yerine:.concat

[1, 2].concat([3, 4]) // [1, 2, 3, 4]

Tüm öğeleri bir diziden diğerine verimli bir şekilde eklemek istiyorsanız , .push yöntemini kullanmanız gerekir :

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]

+Operatörün davranışı ECMA-262 5e Bölüm 11.6.1'de tanımlanmıştır :

11.6.1 Toplama operatörü (+)

Toplama operatörü dize birleştirme veya sayısal toplama yapar. Üretim AdditiveExpression : AdditiveExpression + MultiplicativeExpressionşu şekilde değerlendirilir:

  1. Izin vermek lrefdeğerlendirme sonucu olsun AdditiveExpression.
  2. Let lvalolmak GetValue(lref).
  3. Izin vermek rrefdeğerlendirme sonucu olsun MultiplicativeExpression.
  4. Let rvalolmak GetValue(rref).
  5. Let lprimolmak ToPrimitive(lval).
  6. Let rprimolmak ToPrimitive(rval).
  7. Eğer Type(lprim)bir Stringya da Type(rprim)olduğu String, daha sonra
    1. Birleştirme işleminin sonucu olan Dizeyi ve ToString(lprim)ardındanToString(rprim)
  8. İçin ilave işlemi uygulama sonucunu döndürür ToNumber(lprim)ve ToNumber(rprim). Aşağıdaki Not'a bakınız 11.6.3.

Her işlenenin dönüştürüldüğünü görebilirsiniz ToPrimitive. Daha fazla okuyarak ToPrimitive, dizileri her zaman dizelere dönüştürerek bu sonucu üreteceğimizi bulabiliriz .


7
Bu cevap +1 olarak sadece sorunu açıklamakla kalmaz, aynı zamanda nasıl doğru yapılacağını da açıklar.
schnaader

3
burada küçük bir tmi var, ama schnaader'a katılıyorum. En iyi yanıtlar, sorulan sorunu / hatayı / davranışı açıklar ve ardından istenen sonucun nasıl üretileceğini gösterir. +1
matthewdunnam

1
Neden daha ayrıntılı kullanmak istiyorsunuz Array.prototype.push.apply(data, [3, 4])yerine data.concat([3,4])?
evilcelery

5
@evilcelery: Farklı amaçlara hizmet ediyorlar. yeni bir Dizi concatüretir , daha uzun çağrı mevcut bir Diziyi verimli bir şekilde genişletir .
Jeremy Banks

1
[].push.apply(data, [3,4])Biraz daha az ayrıntı için kullanabilirsiniz . Ayrıca, değerini değiştiren diğer insanlara karşı dayanıklı olması garanti edilir Array.
Sam Tobin-Hochstadt

43

İki diziyi sanki dize gibi ekler .

İlk dizi için dize temsili "1,2" ve ikincisi "3,4" olacaktır . Dolayısıyla, +işaret bulunduğunda, dizileri toplayamaz ve sonra bunları dize olarak birleştiremez.


Evet, akla gelen ilk ve benzersiz açıklama bu ama çok garip bir davranış değil mi? belki bazı karanlık, bilinmeyen bir işlem / dönüşüm yapılıyor ve
iç kısımları

40

+Concats dizeleri, bu nedenle dizeleri diziler dönüştürür.

[1,2] + [3,4]
'1,2' + '3,4'
1,23,4

Dizileri birleştirmek için kullanın concat.

[1,2].concat([3,4])
[1,2,3,4]

21

JavaScript'te, ikili toplama operatörü ( +) hem sayısal toplama hem de dize birleştirmeyi gerçekleştirir. Ancak, ilk argüman ne bir sayı ne de bir dize olduğunda, onu bir dizgiye dönüştürür (dolayısıyla " 1,2"), o zaman aynı işlemi ikinci " 3,4" ile yapar ve bunları " " ile birleştirir 1,23,4.

Bunun yerine Dizilerin "concat" yöntemini kullanmayı deneyin:

var a = [1, 2];
var b = [3, 4];
a.concat(b) ; // => [1, 2, 3, 4];

19

Tek tek dizileri dizelere dönüştürüyor, sonra dizeleri birleştiriyor.


14

Görünüşe göre JavaScript dizilerinizi dizelere dönüştürüyor ve birleştiriyor. Birlikte tuples eklemek istiyorsanız, bir döngü veya bir harita işlevi kullanmanız gerekir.


14

[1,2]+[3,4] JavaScript'te değerlendirme ile aynıdır:

new Array( [1,2] ).toString() + new Array( [3,4] ).toString();

ve böylece sorununuzu çözmek için en iyi şey, yerinde veya yeni bir dizi oluşturmadan iki dizi eklemek olacaktır:

var a=[1,2];
var b=[3,4];
a.push.apply(a, b);

12

Tam olarak yapmasını istediğin şeyi yapıyor.

Birlikte eklediğiniz, göründüğü gibi sayılar değil, dizi referanslarıdır (JS, dizelere dönüşür). Biraz birlikte dizeler eklemek gibi: "hello " + "world"="hello world"


5
hehe, herzaman istediğimi yapar. Sorun iyi soruyu sormak. Beni ilgilendiren şey, dizileri eklediğinizde toString () yorumudur.
okeen


8

Çünkü + operatörü, sayı değilse, işlenenlerin dize olduğunu varsayar. Yani, önce onları dizeye dönüştürür ve bir sayı değilse, nihai sonucu vermek için karar verir. Ayrıca, dizileri desteklemez.


2
+ İşleci, işlenenlerin dizeler olduğunu varsayamıyor, çünkü diğerleri arasında 1 + 1 == 2. Çünkü '+' diziler için tanımlanmamıştır, bu yüzden onları strelemek içindir.
okeen

0

Buradaki bazı cevaplar, beklenmeyen istenmeyen çıktının ( '1,23,4') nasıl gerçekleştiğini, bazıları ise beklenen çıktı ( [1,2,3,4]) olarak varsayıldıklarının nasıl elde edileceğini açıkladı , yani dizi birleştirme. Ancak, istenen istenen çıktının doğası aslında biraz belirsizdir, çünkü orijinal soru basitçe "Bir dizinin elemanlarını bir başkasına eklemek istedim ..." yazıyor. Bu , dizi birleştirme anlamına gelebilir, ancak aynı zamanda tuple ekleme (örneğin burada ve burada ) anlamına da gelebilir , yani bir dizideki öğelerin skaler değerlerini ikincideki karşılık gelen öğelerin skaler değerlerine ekleme, örneğin birleştirme [1,2]ve [3,4]elde etme[4,6] .

Her iki dizinin de aynı düzen / uzunluğa sahip olduğunu varsayarsak, burada basit bir çözüm vardır:

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

Sadece basit bir "+" işareti kullanan başka bir sonuç:

[1,2]+','+[3,4] === [1,2,3,4]

Yani böyle bir şey işe yaramalı (ama!):

var a=[1,2];
var b=[3,4];
a=a+','+b; // [1,2,3,4]

... ancak a değişkenini bir Array'dan String'e dönüştürür! Aklında bulunsun.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.