web-dev-qa-db-ja.com

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

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

[1,2] + [3,4]

次のように応答しました:

"1,23,4"

何が起こっている?

398
okeen

+演算子は配列に対して定義されていません

起こることは、Javascriptが配列を文字列に変換し、それらを連結することです。

更新

この質問とその結果としての私の答えは多くの注目を集めているので、+演算子がどのように動作するかについてoverviewを持つことは有用で関連があると感じました一般的な。

だから、ここに行く。

E4Xおよび実装固有のものを除き、Javascript(ES5以降)には6ビルトイン データ型 があります。

  1. Undefined
  2. ヌル
  3. ブール
  4. ひも
  5. 対象

typeof多少混乱を招く Nullの場合はobject、呼び出し可能オブジェクトの場合はfunctionですが、Nullは実際にはオブジェクトではなく、厳密に言えば、仕様に準拠したJavascript実装ではすべての関数がオブジェクトと見なされます。

そうです-Javascriptにはプリミティブ配列がありません; Arrayと呼ばれるObjectのインスタンスのみが、痛みを和らげるための構文糖衣を備えています。

さらに混乱を加えると、new Number(5)new Boolean(true)new String("abc")などのラッパーエンティティはすべてobject型であり、数値、ブール値、文字列ではありません。それにもかかわらず、算術演算子のNumberおよびBooleanは数値として動作します。

簡単ですか?それがすべて終わったので、概要自体に進むことができます。

オペランドの種類ごとの+の異なる結果の種類

            || 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 で指摘したように、NumberBoolean、およびカスタムの+などのオブジェクトの特定の場合演算子は必ずしも文字列の結果を生成しません。オブジェクトからプリミティブへの変換の実装によって異なる場合があります。たとえば、var o = { valueOf:function () { return 4; } };o + 2;を評価すると6numberが生成され、o + '2'を評価すると'42'stringが生成されます。

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

506
Saul

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. lrefAdditiveExpressionの評価結果とします。
  2. lvalGetValue(lref)とします。
  3. rrefMultiplicativeExpressionの評価結果とします。
  4. rvalGetValue(rref)とします。
  5. lprimToPrimitive(lval)とします。
  6. rprimToPrimitive(rval)とします。
  7. Type(lprim)Stringである場合、またはType(rprim)Stringである場合、
    1. ToString(lprim)に続いてToString(rprim)を連結した結果である文字列を返します
  8. ToNumber(lprim)およびToNumber(rprim)に加算演算を適用した結果を返します。 11.6.3の下の注を参照してください。

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

244
Jeremy Banks

2つのarraysstringsであるかのように追加します。

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

43
Doug

+は文字列を連結するため、配列を文字列に変換します。

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

配列を結合するには、concatを使用します。

[1,2].concat([3,4])
[1,2,3,4]
40
Rocket Hazmat

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

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

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

個々の配列を文字列に変換してから、文字列を結合します。

19
tadman

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

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

したがって、問題を解決するには、2つの配列をその場で追加するか、新しい配列を作成せずに追加するのが最善です。

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

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

14
Adam Fabicki

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

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

12
Jamie Dixon

javaScriptで演算子をオーバーロードできるが、できない場合: Javascriptでカスタム演算子のオーバーロードを定義できますか? 「= = "比較する前に文字列に変換する演算子: http://blogger.xs4all.nl/peterned/archive/2009/04/01/462517.aspx

8
George Birbilis

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

8
Prashant Singh

ここでのいくつかの答えは、予期しない望ましくない出力('1,23,4')がどのように発生するかを説明し、いくつかは、期待される望ましい出力([1,2,3,4])であると仮定するもの、つまり配列連結を取得する方法を説明しました。ただし、元の質問は単に「配列の要素を別の要素に追加したかった」と述べているだけなので、期待される望ましい出力の性質は実際には多少あいまいです。 couldは配列の連結を意味しますが、alsoはタプルの追加を意味します(例 here および here )、つまり、1つの配列の要素のスカラー値を2番目の配列の対応する要素のスカラー値に追加します。 [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]
0
Andrew Willems

単純な「+」記号を使用した別の結果は次のとおりです。

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

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

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

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

0
Blackhead