¿Por qué es [1,2] + [3,4] = "1,23,4" en JavaScript?


Quería añadir los elementos de una matriz en otra, así que probé esto:

[1,2] + [3,4]

Respondió con:

"1,23,4"

¿Qué está pasando?

Author: Sнаđошƒаӽ, 2011-08-19

13 answers

El operador + no está definido para los arrays.

Lo que sucede es que Javascript convierte matrices en cadenas y las concatena.

 

Actualización

Dado que esta pregunta y, en consecuencia, mi respuesta está recibiendo mucha atención, sentí que sería útil y relevante tener una descripción sobre cómo se comporta el operador + en general también.

Así que, aquí va.

Excluidos E4X y cosas específicas de la implementación, Javascript (a partir de ES5) tiene 6 tipos de datos incorporados :

  1. Indefinido
  2. Null
  3. Booleano
  4. Número
  5. String
  6. Objeto

Tenga en cuenta que aunque typeof vuelve un poco confusamente object para Null y function para Objetos llamables, Null en realidad no es un Objeto y estrictamente hablando, en las implementaciones Javascript que cumplen con las especificaciones, todas las funciones son considerados Objetos.

Así es - Javascript no tiene arrays primitivos como tales; solo instancias de un Objeto llamado Array con algo de azúcar sintáctica para aliviar el dolor.

Añadiendo más a la confusión, entidades envolventes como new Number(5), new Boolean(true) y new String("abc") son todos de tipo object, no números, booleanos o cadenas como uno podría esperar. Sin embargo, para los operadores aritméticos Number y Boolean se comportan como números.

Fácil, ¿eh? Con todo eso fuera del camino, podemos pase a la vista general en sí.

Diferentes tipos de resultados de + por tipos de operando

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

* se aplica a Chrome13, FF6, Opera11 e IE9. La comprobación de otros navegadores y versiones se deja como un ejercicio para el lector.

Nota: Como señala CMS , para ciertos casos de objetos como Number, Boolean y los personalizados el operador + no necesariamente produce un resultado de cadena. Puede variar dependiendo de la implementación del objeto a la conversión primitiva. Por ejemplo var o = { valueOf:function () { return 4; } }; evaluar o + 2; produce 6, a number, evaluar o + '2' produce '42', a string.

Para ver cómo se generó la tabla general, visite http://jsfiddle.net/1obxuc7m /

 499
Author: Saul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:02:50

El operador de JavaScript + tiene dos propósitos: agregar dos números o unir dos cadenas. No tiene un comportamiento específico para los arrays, por lo que los convierte en cadenas y luego los une.

Si desea unir dos matrices para producir una nueva, use el método .concat en su lugar:

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

Si desea agregar eficientemente todos los elementos de una matriz a otra, debe usar el .método 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]

El comportamiento de los + el operador se define en la sección ECMA-262 5e 11.6.1:

11.6.1 El operador de suma ( + )

El operador de suma realiza concatenación de cadenas o suma numérica. La producción AdditiveExpression : AdditiveExpression + MultiplicativeExpression se evalúa de la siguiente manera:

  1. Sea lref el resultado de evaluar AdditiveExpression.
  2. Sea lval GetValue(lref).
  3. Sea rref el resultado de evaluar MultiplicativeExpression.
  4. Sea rval GetValue(rref).
  5. Sea lprim ToPrimitive(lval).
  6. Sea rprim ToPrimitive(rval).
  7. Si Type(lprim) es String o Type(rprim) es String, entonces
    1. Devuelve la cadena que es el resultado de concatenar ToString(lprim) seguido de ToString(rprim)
  8. Devuelve el resultado de aplicar la operación de adición a ToNumber(lprim) y ToNumber(rprim). Véase la nota 11.6.3.

Puedes ver que cada operando se convierte ToPrimitive. Al leer más podemos encontrar que ToPrimitive siempre convertirá matrices en cadenas, produciendo este resultado.

 242
Author: Jeremy Banks,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-15 08:55:23

Añade los dos matrices como si fueran cadenas.

La representación de cadena para el primer array sería "1,2" y el segundo sería "3,4". Así que cuando se encuentra el signo +, no puede sumar matrices y luego concatenar como cadenas.

 43
Author: Doug,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-19 17:09:30

El + concatea cadenas, por lo que convierte los arrays en cadenas.

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

Para combinar matrices, use concat.

[1,2].concat([3,4])
[1,2,3,4]
 39
Author: Rocket Hazmat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-19 16:58:50

En JavaScript, el operador de adición binaria (+) realiza tanto la adición numérica como la concatenación de cadenas. Sin embargo, cuando su primer argumento no es ni un número ni una cadena entonces lo convierte en una cadena (de ahí "1,2") entonces hace lo mismo con el segundo "3,4" y los concatena a "1,23,4".

Intente usar el método" concat " de matrices en su lugar:

var a = [1, 2];
var b = [3, 4];
a.concat(b) ; // => [1, 2, 3, 4];
 21
Author: maerics,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-19 17:00:30

Está convirtiendo los arrays individuales en cadenas, luego combinando las cadenas.

 19
Author: tadman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-19 16:57:29

Parece que JavaScript está convirtiendo sus matrices en cadenas y uniéndolas. Si desea agregar tuplas juntas, tendrá que usar un bucle o una función de mapa.

 14
Author: Adam Fabicki,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-19 16:57:28

[1,2]+[3,4] en JavaScript es lo mismo que evaluar:

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

Y así para resolver su problema, lo mejor sería agregar dos matrices en su lugar o sin crear una nueva matriz:

var a=[1,2];
var b=[3,4];
a.push.apply(a, b);
 14
Author: user286806,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-27 01:58:42

Está haciendo exactamente lo que le pediste que hiciera.

Lo que está sumando son referencias de matriz (que JS convierte en cadenas), no números como parece. Es un poco como agregar cuerdas juntas: "hello " + "world" = "hello world"

 12
Author: Jamie Dixon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-19 16:57:03

Sería bueno si pudiera sobrecargar los operadores en JavaScript, pero no puede: ¿Puedo definir sobrecargas de operadores personalizados en Javascript? solo puede hackear el operador "= = " que se convierte en cadenas antes de comparar: http://blogger.xs4all.nl/peterned/archive/2009/04/01/462517.aspx

 8
Author: George Birbilis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:18:02

Es porque, + operador asume que los operandos son cadena, si no son números. Por lo tanto , primero los convierte en cadena y concats para dar el resultado final, si no es un número. Además, no soporta arrays.

 8
Author: Prashant Singh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-20 11:06:17

Otro resultado usando solo un simple signo "+" será:

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

Así que algo como esto debería funcionar (¡pero!):

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

... ¡pero convertirá la variable a de una matriz a Cadena! Tenlo en cuenta.

 0
Author: Blackhead,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-12 09:07:48

Algunas respuestas aquí han explicado cómo ocurre la salida no deseada inesperada ('1,23,4') y algunas han explicado cómo obtener lo que suponen que es la salida deseada esperada ([1,2,3,4]), es decir, la concatenación de matrices. Sin embargo, la naturaleza de la salida deseada esperada es en realidad algo ambigua porque la pregunta original simplemente establece "Quería agregar los elementos de una matriz en otra...". Que podría concatenación de matriz media pero podría también suma de tupla media (e. g. here and here), i.e. adding the scalar values of elements in one array to the scalar values of the corresponding elements in the second, e. g. combining [1,2] and [3,4] to obtain [4,6].

Asumiendo que ambos arrays tienen la misma aridad/longitud, aquí hay una solución 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
Author: Andrew Willems,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:26:07