web-dev-qa-db-fra.com

Pourquoi [1,2] + [3,4] = "1,23,4" en JavaScript?

Je voulais ajouter les éléments d'un tableau à un autre, alors j'ai essayé ceci:

[1,2] + [3,4]

Il a répondu avec:

"1,23,4"

Que se passe-t-il?

398
okeen

L'opérateur + n'est pas défini pour les tableaux .

Qu'est-ce qui se passe, c'est que Javascript convertit les tableaux en chaînes et les concatène.

Mise à jour

Depuis que cette question et par conséquent ma réponse attirent beaucoup d’attention, j’ai pensé qu’il serait utile et pertinent d’avoir un aperçu de la manière dont le code + opérateur se comporte en général aussi.

Alors, voilà.

En excluant E4X et les éléments spécifiques à l’implémentation, Javascript (à partir de ES5) intègre 6 types de données :

  1. Undefined
  2. Nul
  3. Booléen
  4. Nombre
  5. Chaîne
  6. Objet

Notez que bien que typeofretourne un peu déroutantobject pour Null et function pour les objets appelables, Null n'est en réalité pas un objet et à proprement parler, dans la spécification Implémentations Javascript conformes à toutes les fonctions sont considérées comme des objets.

C'est vrai - Javascript n'a aucun tableau primitif en tant que tel; seules les instances d'un objet appelé Array avec du sucre syntaxique pour soulager la douleur.

Pour ajouter à la confusion, les entités d'encapsulation telles que new Number(5), new Boolean(true) et new String("abc") sont toutes de type object, et non de nombres, booléens ou chaînes. comme on pouvait s'y attendre. Néanmoins, pour les opérateurs arithmétiques, Number et Boolean se comportent comme des nombres.

Facile, hein? Après tout cela, nous pouvons passer à la vue d'ensemble elle-même.

Différents types de résultats de + Par types d'opérandes

            || 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 | 

* s'applique à Chrome13, FF6, Opera11 et IE9. La vérification des autres navigateurs et versions est laissée comme un exercice pour le lecteur.

Remarque: Comme indiqué par CMS , pour certains cas d'objets tels que Number, Boolean et les opérateurs personnalisés, l'opérateur + ne produit pas nécessairement un résultat sous forme de chaîne. Elle peut varier en fonction de la mise en œuvre de la conversion objet à primitive. Par exemple, var o = { valueOf:function () { return 4; } }; évaluer o + 2; Produit 6, Un number, évaluer o + '2' Produit '42', Un string.

Pour voir comment la table de synthèse a été générée, visitez http://jsfiddle.net/1obxuc7m/

506
Saul

L'opérateur + De JavaScript a deux objectifs: ajouter deux nombres ou joindre deux chaînes. Il n'a pas de comportement spécifique pour les tableaux, il les convertit donc en chaînes, puis les rejoint.

Si vous souhaitez joindre deux tableaux pour en créer un nouveau, utilisez la méthode .concat à la place:

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

Si vous souhaitez ajouter efficacement tous les éléments d'un tableau à un autre, vous devez utiliser la méthode .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]

Le comportement de l'opérateur + Est défini dans ECMA-262 5e chapitre 11.6.1 :

11.6.1 L'opérateur Addition (+)

L'opérateur d'addition effectue une concaténation de chaîne ou une addition numérique. La production AdditiveExpression : AdditiveExpression + MultiplicativeExpression Est évaluée comme suit:

  1. Soit lref le résultat de l’évaluation de AdditiveExpression.
  2. Soit lval être GetValue(lref).
  3. Soit rref le résultat de l’évaluation de MultiplicativeExpression.
  4. Soit rval être GetValue(rref).
  5. Soit lprim être ToPrimitive(lval).
  6. Soit rprim être ToPrimitive(rval).
  7. Si Type(lprim) est String ou Type(rprim) est String, alors
    1. Renvoie la chaîne résultant de la concaténation de ToString(lprim) suivi de ToString(rprim)
  8. Renvoie le résultat de l'application de l'opération d'addition sur ToNumber(lprim) et ToNumber(rprim). Voir la note ci-dessous 11.6.3.

Vous pouvez voir que chaque opérande est converti ToPrimitive. En lisant plus loin, nous pouvons constater que ToPrimitive convertira toujours les tableaux en chaînes, produisant ce résultat.

244
Jeremy Banks

Il ajoute les deux tableaux comme s'ils étaient chaînes.

La représentation sous forme de chaîne pour le premier tableau serait "1,2" et le second serait "3,4". Alors quand le + _ est trouvé, il ne peut pas résumer de tableaux, puis les concaténer en tant que chaînes.

43
Doug

Le + _ concats les chaînes, donc il convertit les tableaux en chaînes.

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

Pour combiner des tableaux, utilisez concat.

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

En JavaScript, l'opérateur d'addition binaire (+) effectue une addition numérique et une concaténation de chaînes. Cependant, quand son premier argument n'est ni un nombre ni une chaîne, il le convertit en chaîne (d'où "1,2 ") alors il fait la même chose avec le second" 3,4 "et les concatène en" 1,23,4 ".

Essayez plutôt d’utiliser la méthode "concat" de Arrays:

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

Il convertit les tableaux individuels en chaînes, puis combine les chaînes.

19
tadman

[1,2]+[3,4] en JavaScript équivaut à évaluer:

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

et pour résoudre votre problème, la meilleure chose à faire serait d’ajouter deux tableaux sur place ou sans créer un nouveau tableau:

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

Il semble que JavaScript transforme vos tableaux en chaînes et les associe. Si vous voulez ajouter des nuplets ensemble, vous devrez utiliser une boucle ou une fonction de carte.

14
Adam Fabicki

Il fait exactement ce que vous lui avez demandé de faire.

Ce que vous ajoutez ensemble sont des références de tableau (que JS convertit en chaînes), et non des nombres comme il semble. C'est un peu comme ajouter des chaînes ensemble: "hello " + "world" = "hello world"

12
Jamie Dixon

ce serait bien si vous pouviez surcharger des opérateurs en JavaScript mais vous ne pouvez pas: puis-je définir des surcharges d’opérateurs personnalisées en Javascript? vous ne pouvez pirater l’opérateur "==" qui convertit en chaînes avant de comparer: - http://blogger.xs4all.nl/peterned/archive/2009/04/01/462517.aspx

8
George Birbilis

C'est parce que, l'opérateur + suppose que les opérandes sont des chaînes, s'ils ne sont pas des nombres. Donc, il les convertit d'abord en chaîne et concat pour donner le résultat final, si ce n'est pas un nombre. En outre, il ne prend pas en charge les tableaux.

8
Prashant Singh

Certaines réponses ici ont expliqué comment la sortie inattendue non désirée ('1,23,4') arrive et certains ont expliqué comment obtenir ce qu’ils supposaient être la sortie attendue ([1,2,3,4]), c’est-à-dire concaténation de tableau. Cependant, la nature de la sortie souhaitée est quelque peu ambiguë, car la question initiale se bornait à indiquer "Je voulais ajouter les éléments d’un tableau à un autre ...". Cela pourrait signifier une concaténation de tableaux, mais il pourrait aussi également ajouter un tuple (par exemple ici et ici ), c’est-à-dire l’ajout des valeurs scalaires des éléments d’un tableau aux valeurs scalaires des éléments correspondants du second, par exemple combinant [1,2] et [3,4] obtenir [4,6].

En supposant que les deux tableaux ont la même taille/longueur, voici une solution simple:

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

Un autre résultat utilisant simplement un simple signe "+" sera:

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

Donc, quelque chose comme ça devrait marcher (mais!):

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

... mais cela convertira la variable a d'un tableau en chaîne! Garde le en mémoire.

0
Blackhead