JavaScriptで[1,2] + [3,4] =“ 1,23,4”となるのはなぜですか?


405

配列の要素を別の配列に追加したかったので、これを試しました:

[1,2] + [3,4]

それは次のように応答しました:

"1,23,4"

何が起こっている?


1
このトピックに関連する質問は次のとおりです。stackoverflow.com
Xavi

29
あはは、サディストインタビュアーは次のような質問をすることもできます-これが何を返すか[1,2] + [5,6,7] [1,2]。どうして?
shabunc

9
[1,2] + [3,4]は、今週、firebugでalert( 'crap')の後に最も評価された式だと思います。
okeen 2011

6
笑いたい ?[] + []、{} + []、{} + {}、[] + {}をお試しください
Intrepidd

1
@shabunc-理由[5,6,7][1,2]72番目の配列の最後の項目を使用するためです。Oo
vsync 2015

回答:


518

+オペレータは、アレイ用に定義されていません

何が起こるかというと、Javascriptは配列を文字列に変換し、それらを連結します

 

更新

この質問とその結果の私の答えは非常に注目を集めているので、私はオペレーターが一般的にどのように振る舞うのかについての概要を知ることは有用で適切だと感じました+

だから、ここに行きます。

E4Xおよび実装固有のものを除いて、JavaScript(ES5現在)には6つの組み込みデータ型があります

  1. 未定義
  2. ヌル
  3. ブール
  4. ストリング
  5. オブジェクト

注意がいることをtypeof 、やや紛らわしい返し objectヌルのためにとfunction呼び出し可能オブジェクトのために、ヌルが実際にオブジェクトと厳密ではありません、仕様準拠のJavaScript実装ですべての機能がオブジェクトであると考えられています。

そうです-Javascriptにはそのようなプリミティブ配列はありません。ObjectのインスタンスのみがArray、痛みを和らげるためにいくつかの構文糖で呼び出されました。

混乱にさらに追加するとnew Number(5)new Boolean(true)やなどのラッパーエンティティnew String("abc")はすべて、object数値、ブール値、または文字列ではなく、すべて型です。それにも関わらず、算術演算子のためNumberBoolean数字として振る舞います。

簡単でしょ?以上がすべて終了したので、概要に移ります。

+オペランドタイプ別の異なる結果タイプ

            || 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;生成6number評価、o + '2'生産'42'string

概要テーブルがどのように生成されたかを確認するには、http://jsfiddle.net/1obxuc7m/にアクセスしてください。


244

JavaScriptの+演算子には、2つの数値を追加すること、または2つの文字列を結合するという2つの目的があります。配列には特定の動作がないため、配列に文字列に変換してから結合します。

2つの配列を結合して新しい配列を作成する場合は、.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]

+演算子の動作はECMA-262 5eセクション11.6.1で定義されています

11.6.1加算演算子(+)

加算演算子は、文字列連結または数値加算を実行します。生産AdditiveExpression : AdditiveExpression + MultiplicativeExpressionは次のように評価されます。

  1. lrefを評価した結果としましょうAdditiveExpression
  2. してみましょうlvalことGetValue(lref)
  3. rrefを評価した結果としましょうMultiplicativeExpression
  4. してみましょうrvalことGetValue(rref)
  5. してみましょうlprimことToPrimitive(lval)
  6. してみましょうrprimことToPrimitive(rval)
  7. Type(lprim)あるStringかでType(rprim)あるString場合、
    1. 連結した結果である文字列を返しますToString(lprim)が続くとToString(rprim)
  8. ToNumber(lprim)とに加算演算を適用した結果を返しToNumber(rprim)ます。下記の11.6.3の注を参照してください。

各オペランドが変換されていることがわかりToPrimitiveます。さらに読むToPrimitiveと、配列が常に文字列に変換され、この結果が生成されることがわかります。


7
この回答としての+1は、問題を説明するだけでなく、それを正しく行う方法も説明します。
シュナーダー、2011

3
ここには少しtmiがありますが、私はシュナーダーに同意します。最良の回答は、質問されている問題/エラー/動作を説明し、意図した結果を生成する方法を示します。+1
matthewdunnam 2011

1
Array.prototype.push.apply(data, [3, 4])代わりに、より詳細なものを使用するのはなぜdata.concat([3,4])ですか?
悪酒屋

5
@evilcelery:彼らはさまざまな目的を果たします。新しい配列をconcat作成します。呼び出しが長いほど、既存の配列を効率的に拡張します。
Jeremy Banks、

1
[].push.apply(data, [3,4])少し冗長に使用できます。また、それはの値を変更する他の人々に耐性があることが保証されていますArray
Sam Tobin-Hochstadt 2012年

43

それらは文字列であるかのように2つの配列を追加します

最初の配列の文字列表現は"1,2"になり、2番目の配列は"3,4"になります。したがって、+符号が見つかると、配列を合計して文字列として連結することはできません。


はい、それは頭に浮かぶ最初でユニークな説明ですが、それは非常に奇妙な行動ではありませんか?多分、暗く、知られていない操作/変換が行われているので、私は内部を知りたいです:P
okeen '19

40

+concats文字列は、それは文字列に配列を変換します。

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

配列を組み合わせるには、を使用しますconcat

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

21

JavaScriptでは、2項加算演算子(+)は数値加算と文字列連結の両方を実行します。ただし、最初の引数が数値でも文字列でもない場合は、それを文字列(つまり " 1,2")に変換し、2番目の " 3,4" でも同じことを行い、それらを " 1,23,4"に連結します。

代わりに、配列の「連結」メソッドを使用してみてください。

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


14

JavaScriptが配列を文字列に変換して結合しているようです。タプルを一緒に追加したい場合は、ループまたはマップ関数を使用する必要があります。


14

[1,2]+[3,4] JavaScriptでの評価と同じです:

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

したがって、問題を解決するには、2つの配列を同じ場所に追加するか、新しい配列を作成しないでください。

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

12

それはまさにあなたがそれをするように頼んだことをしています。

一緒に追加しているのは、配列参照(JSが文字列に変換する)であり、見かけ上の数値ではありません。これは文字列を一緒に追加するようなものです:"hello " + "world"="hello world"


5
hehe、それはいつも私が尋ねたことを常にします。問題は良い質問をすることです。興味深いのは、配列を追加したときのtoString()による配列の解釈です。
okeen


8

+演算子は、オペランドが数値でない場合、オペランドが文字列であると想定するためです。したがって、最初にそれらを文字列に変換し、連結していない場合は、最終的な結果を返します。また、配列はサポートしていません。


2
+演算子は、特に1 + 1 == 2であるため、オペランドが文字列であると仮定することはできません。これは、配列に '+'が定義されていないため、それらをtoString-sするためです。
okeen 2011

0

ここでは、予期しない望ましくない出力('1,23,4')がどのように発生するかを説明する回答と、期待される望ましい出力([1,2,3,4])であると想定されるもの、つまり配列連結を取得する方法を説明する回答があります。ただし、元の質問は単に「配列の要素を別の要素に追加したかった」と述べているため、期待される望ましい出力の性質は実際にはややあいまいです。すなわち、可能性配列の連結を意味するが、それは可能性平均タプル添加(例えば、ここでおよびここで)、すなわち組み合わせ例えば、第二の対応する要素のスカラー値、1つの配列内の要素のスカラー値を加算[1,2]し、[3,4]得ること[4,6]

両方の配列のアリティ/長さが同じであると仮定すると、次の1つの簡単な解決策があります。

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

単純な「+」記号を使用した別の結果は次のようになります。

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

したがって、このようなものが機能するはずです(しかし!):

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

...しかし、変数aを配列から文字列に変換します!それを覚えておいてください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.