¿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?
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 :
- Indefinido
- Null
- Booleano
- Número
- String
- 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.
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 /
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:
- Sea
lref
el resultado de evaluarAdditiveExpression
.- Sea
lval
GetValue(lref)
.- Sea
rref
el resultado de evaluarMultiplicativeExpression
.- Sea
rval
GetValue(rref)
.- Sea
lprim
ToPrimitive(lval)
.- Sea
rprim
ToPrimitive(rval)
.- Si
Type(lprim)
esString
oType(rprim)
esString
, entonces
- Devuelve la cadena que es el resultado de concatenar
ToString(lprim)
seguido deToString(rprim)
- Devuelve el resultado de aplicar la operación de adición a
ToNumber(lprim)
yToNumber(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.
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.
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]
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];
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.
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.
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);
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"
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
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.
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.
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]
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