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?
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.
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 :
Notez que bien que typeof
retourne 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/
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:
- Soit
lref
le résultat de l’évaluation deAdditiveExpression
.- Soit
lval
êtreGetValue(lref)
.- Soit
rref
le résultat de l’évaluation deMultiplicativeExpression
.- Soit
rval
êtreGetValue(rref)
.- Soit
lprim
êtreToPrimitive(lval)
.- Soit
rprim
êtreToPrimitive(rval)
.- Si
Type(lprim)
estString
ouType(rprim)
estString
, alors
- Renvoie la chaîne résultant de la concaténation de
ToString(lprim)
suivi deToString(rprim)
- Renvoie le résultat de l'application de l'opération d'addition sur
ToNumber(lprim)
etToNumber(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.
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.
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]
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];
Il convertit les tableaux individuels en chaînes, puis combine les chaînes.
[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);
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.
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"
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
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.
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]
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.