Esto es válido y devuelve la cadena "10"
en JavaScript ( más ejemplos aquí ):
console.log(++[[]][+[]]+[+[]])
¿Por qué? ¿Que está sucediendo aquí?
Si lo dividimos, el lío es igual a:
++[[]][+[]]
+
[+[]]
En JavaScript, es cierto que +[] === 0
. +
convierte algo en un número y, en este caso, se reducirá a +""
o 0
(consulte los detalles de la especificación a continuación).
Por lo tanto, podemos simplificarlo ( ++
tiene precedencia sobre +
):
++[[]][0]
+
[0]
Porque [[]][0]
significa: obtener el primer elemento de [[]]
, es cierto que:
[[]][0]
devuelve la matriz interna ( []
). Debido a las referencias, es incorrecto decirlo [[]][0] === []
, pero llamemos a la matriz interna A
para evitar la notación incorrecta.
++
antes de su operando significa "incrementar en uno y devolver el resultado incrementado". Entonces ++[[]][0]
es equivalente a Number(A) + 1
(o +A + 1
).
Nuevamente, podemos simplificar el desorden en algo más legible. Reemplacemos []
por A
:
(+[] + 1)
+
[0]
Antes de que +[]
pueda coaccionar la matriz en el número 0
, primero debe coaccionarse en una cadena, que es ""
, nuevamente. Finalmente, 1
se agrega, lo que da como resultado 1
.
(+[] + 1) === (+"" + 1)
(+"" + 1) === (0 + 1)
(0 + 1) === 1
Simplifiquémoslo aún más:
1
+
[0]
Además, esto es cierto en JavaScript:, [0] == "0"
porque está uniendo una matriz con un elemento. La unión concatenará los elementos separados por ,
. Con un elemento, puede deducir que esta lógica dará como resultado el primer elemento en sí.
En este caso, +
ve dos operandos: un número y una matriz. Ahora está tratando de obligar a los dos al mismo tipo. Primero, la matriz se convierte en una cadena "0"
, luego, el número se convierte en una cadena ( "1"
). Cadena de número Cadena+
===
.
"1" + "0" === "10" // Yay!
Detalles de la especificación para +[]
:
Este es un gran laberinto, pero para hacerlo +[]
, primero se está convirtiendo en una cadena porque eso es lo que +
dice:
11.4.6 Operador Unario +
El operador unario + convierte su operando al tipo de Número.
La producción UnaryExpression: + UnaryExpression se evalúa de la siguiente manera:
Sea expr el resultado de evaluar UnaryExpression.
Regrese ToNumber (GetValue (expr)).
ToNumber()
dice:
Objeto
Aplicar los siguientes pasos:
Deje que primValue sea ToPrimitive (argumento de entrada, cadena de sugerencias).
Regrese ToString (primValue).
ToPrimitive()
dice:
Objeto
Devuelve un valor predeterminado para el objeto. El valor predeterminado de un objeto se recupera llamando al método interno [[DefaultValue]] del objeto, pasando la sugerencia opcional PreferredType. El comportamiento del método interno [[DefaultValue]] está definido por esta especificación para todos los objetos ECMAScript nativos en 8.12.8.
[[DefaultValue]]
dice:
8.12.8 [[DefaultValue]] (pista)
Cuando se llama al método interno [[DefaultValue]] de O con hint String, se toman los siguientes pasos:
Sea toString el resultado de llamar al método interno [[Get]] del objeto O con el argumento "toString".
Si IsCallable (toString) es verdadero, entonces,
una. Sea str el resultado de llamar al método interno [[Call]] de toString, con O como este valor y una lista de argumentos vacía.
B. Si str es un valor primitivo, devuelve str.
El .toString
de una matriz dice:
15.4.4.2 Array.prototype.toString ()
Cuando se llama al método toString, se siguen los siguientes pasos:
Sea matriz el resultado de llamar a ToObject en este valor.
Sea func el resultado de llamar al método interno [[Get]] de la matriz con el argumento "join".
Si IsCallable (func) es falso, entonces deje que func sea el método estándar incorporado Object.prototype.toString (15.2.4.2).
Devuelve el resultado de llamar al método interno [[Call]] de func proporcionando una matriz como este valor y una lista de argumentos vacía.
Así que +[]
se reduce a +""
porque [].join() === ""
.
Nuevamente, +
se define como:
11.4.6 Operador Unario +
El operador unario + convierte su operando al tipo de Número.
La producción UnaryExpression: + UnaryExpression se evalúa de la siguiente manera:
Sea expr el resultado de evaluar UnaryExpression.
Regrese ToNumber (GetValue (expr)).
ToNumber
se define ""
como:
El MV de StringNumericLiteral ::: [vacío] es 0.
Así +"" === 0
y así +[] === 0
.
++[[]][+[]] => 1 // [+[]] = [0], ++0 = 1
[+[]] => [0]
Entonces tenemos una concatenación de cadenas
1+[0].toString() = 10
Lo siguiente es una adaptación de una publicación de blog que responde a esta pregunta que publiqué mientras esta pregunta aún estaba cerrada. Los enlaces son a (una copia HTML de) la especificación ECMAScript 3, que sigue siendo la línea de base para JavaScript en los navegadores web de uso común en la actualidad.
Primero, un comentario: este tipo de expresión nunca aparecerá en ningún entorno de producción (sano) y solo sirve como ejercicio para determinar qué tan bien el lector conoce los aspectos sucios de JavaScript. El principio general de que los operadores de JavaScript convierten implícitamente entre tipos es útil, al igual que algunas de las conversiones comunes, pero muchos de los detalles en este caso no lo son.
La expresión ++[[]][+[]]+[+[]]
inicialmente puede parecer bastante imponente y oscura, pero en realidad es relativamente fácil dividirla en expresiones separadas. A continuación, simplemente agregué paréntesis para mayor claridad; Puedo asegurarle que no cambian nada, pero si desea verificarlo, no dude en leer sobre el operador de agrupación . Entonces, la expresión se puede escribir más claramente como
( ++[[]][+[]] ) + ( [+[]] )
Desglosando esto, podemos simplificar observando que +[]
evalúa a 0
. Para satisfacer mismo por qué esto es cierto, revisar el operador unario + y seguir el rastro ligeramente tortuoso que termina con ToPrimitive convertir la matriz vacía en una cadena vacía, que luego se convierte finalmente a 0
por ToNumber . Ahora podemos sustituir 0
cada instancia de +[]
:
( ++[[]][0] ) + [0]
Ya es más sencillo. En cuanto a ++[[]][0]
, esa es una combinación del operador de incremento de prefijo ( ++
), un literal de matriz que define una matriz con un solo elemento que es en sí mismo una matriz vacía ( [[]]
) y un descriptor de acceso de propiedad ( [0]
) llamado en la matriz definida por el literal de matriz.
Entonces, podemos simplificar [[]][0]
a solo []
y lo tenemos ++[]
, ¿verdad? De hecho, este no es el caso porque la evaluación ++[]
arroja un error, que inicialmente puede parecer confuso. Sin embargo, un poco de reflexión sobre la naturaleza de ++
deja esto claro: se usa para incrementar una variable (por ejemplo ++i
) o una propiedad de objeto (por ejemplo ++obj.count
). No solo evalúa un valor, sino que también almacena ese valor en algún lugar. En el caso de ++[]
, no tiene dónde poner el nuevo valor (cualquiera que sea) porque no hay ninguna referencia a una propiedad o variable del objeto para actualizar. En términos de especificaciones, esto está cubierto por la operación interna PutValue , a la que llama el operador de incremento de prefijo.
Entonces, ¿qué hace ++[[]][0]
? Bueno, con una lógica similar a +[]
, la matriz interna se convierte en 0
y este valor se incrementa en 1
para darnos un valor final de 1
. El valor de la propiedad 0
en la matriz externa se actualiza 1
y se evalúa toda la expresión 1
.
Esto nos deja con
1 + [0]
... que es un uso simple del operador de suma . Ambos operandos se convierten primero en primitivas y si alguno de los valores primitivos es una cadena, se realiza una concatenación de cadenas; de lo contrario, se realiza una suma numérica. [0]
convierte a "0"
, por lo que se usa la concatenación de cadenas, produciendo "10"
.
Como comentario final, algo que puede no ser evidente de inmediato es que anular uno de los métodos toString()
o cambiará el resultado de la expresión, porque ambos se verifican y se usan si están presentes al convertir un objeto en un valor primitivo. Por ejemplo, lo siguientevalueOf()
Array.prototype
Array.prototype.toString = function() {
return "foo";
};
++[[]][+[]]+[+[]]
... produce "NaNfoo"
. Por qué sucede esto se deja como ejercicio para el lector ...
Hagámoslo simple:
++[[]][+[]]+[+[]] = "10"
var a = [[]][+[]];
var b = [+[]];
// so a == [] and b == [0]
++a;
// then a == 1 and b is still that array [0]
// when you sum the var a and an array, it will sum b as a string just like that:
1 + "0" = "10"
Este se evalúa igual pero un poco más pequeño
+!![]+''+(+[])
por lo que se evalúa a
+(true) + '' + (0)
1 + '' + 0
"10"
Así que ahora lo tienes, prueba este:
_=$=+[],++_+''+$
+ [] evalúa a 0 [...] luego sumando (+ operación) con cualquier cosa convierte el contenido de la matriz en su representación de cadena que consiste en elementos unidos con una coma.
Cualquier otra cosa como tomar el índice de la matriz (tener mayor prioridad que + operación) es ordinal y no es nada interesante.
Quizás las formas más cortas posibles de evaluar una expresión en "10" sin dígitos son:
+!+[] + [+[]]
// "10"
-~[] + [+[]]
// "10"
// ========== Explicación ========== \\
+!+[]
: +[]
Convierte a 0. !0
convierte a true
. +true
convierte a 1. -~[]
= -(-1)
que es 1
[+[]]
: +[]
Convierte a 0. [0]
es una matriz con un solo elemento 0.
Entonces JS evalúa la expresión 1 + [0]
, por lo tanto Number + Array
. Entonces la especificación ECMA funciona: el +
operador convierte ambos operandos en una cadena llamando a las toString()/valueOf()
funciones desde el Object
prototipo base . Opera como una función aditiva si ambos operandos de una expresión son solo números. El truco es que las matrices convierten fácilmente sus elementos en una representación de cadena concatenada.
Algunos ejemplos:
1 + {} // "1[object Object]"
1 + [] // "1"
1 + new Date() // "1Wed Jun 19 2013 12:13:25 GMT+0400 (Caucasus Standard Time)"
Hay una buena excepción en la que dos Objects
sumas dan como resultado NaN
:
[] + [] // ""
[1] + [2] // "12"
{} + {} // NaN
{a:1} + {b:2} // NaN
[1, {}] + [2, {}] // "1,[object Object]2,[object Object]"
Paso a paso, +
convierta el valor en un número y si agrega a una matriz vacía +[]
... ya que está vacía y es igual a 0
, lo hará
Entonces, a partir de ahí, ahora mire su código, es ++[[]][+[]]+[+[]]
...
Y hay un plus entre ellos ++[[]][+[]]
+[+[]]
Entonces estos [+[]]
regresarán [0]
ya que tienen una matriz vacía que se convierte 0
dentro de la otra matriz ...
Entonces, como imagina, el primer valor es una matriz bidimensional con una matriz dentro ... por [[]][+[]]
lo que será igual a [[]][0]
lo que devolverá []
...
Y al final ++
convertirlo y aumentarlo a 1
...
Así que puedes imaginar, 1
+ "0"
será "10"
...
+ '' o + [] evalúa 0.
++[[]][+[]]+[+[]] = 10
++[''][0] + [0] : First part is gives zeroth element of the array which is empty string
1+0
10
La estrella de HGTV, Christina Hall, revela que le diagnosticaron envenenamiento por mercurio y plomo, probablemente debido a su trabajo como manipuladora de casas.
Recientemente salió a la luz un informe policial que acusa a la estrella de 'Love Is Blind', Brennon, de violencia doméstica. Ahora, Brennon ha respondido a los reclamos.
Conozca cómo Wynonna Judd se dio cuenta de que ahora es la matriarca de la familia mientras organizaba la primera celebración de Acción de Gracias desde que murió su madre, Naomi Judd.
Descubra por qué un destacado experto en lenguaje corporal cree que es fácil trazar "tales paralelismos" entre la princesa Kate Middleton y la princesa Diana.
Los inodoros arrojan columnas de aerosol invisibles con cada descarga. ¿Como sabemos? La prueba fue capturada por láseres de alta potencia.
Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?
The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!
¿Sigue siendo efectivo ese lote de repelente de insectos que te quedó del verano pasado? Si es así, ¿por cuánto tiempo?
Anteriormente, Kotaku informó que un hotel Godzilla se estaba abriendo en Tokio este abril. Junto al hotel, estaba programada la aparición de una enorme cabeza de 'Zilla, pero todo lo que hemos visto fueron imágenes conceptuales computarizadas.
Foto: Getty Desde que lanzó The Boring Company hace un año, Elon Musk ha mencionado varios sitios de construcción posibles para el negocio de perforación de túneles y ha descartado una vaga referencia a una aprobación gubernamental "verbal" para un túnel Hyperloop que conecta la ciudad de Nueva York y Washington. , CC. Pero ahora sabemos que al menos un alcalde quiere que Musk perfore un agujero debajo de su ciudad.
Tapas elásticas de silicona de Tomorrow's Kitchen, paquete de 12 | $14 | Amazonas | Código promocional 20OFFKINJALids son básicamente los calcetines de la cocina; siempre perdiéndose, dejando contenedores huérfanos que nunca podrán volver a cerrarse. Pero, ¿y si sus tapas pudieran estirarse y adaptarse a todos los recipientes, ollas, sartenes e incluso frutas en rodajas grandes que sobran? Nunca más tendrás que preocuparte por perder esa tapa tan específica.
Hemos pirateado algunas ciudades industriales en esta columna, como Los Ángeles y Las Vegas. Ahora es el momento de una ciudad militar-industrial-compleja.
El equipo está a la espera de las medallas que ganó en los Juegos Olímpicos de Invierno de 2022 en Beijing, ya que se está resolviendo un caso de dopaje que involucra a la patinadora artística rusa Kamila Valieva.
Miles de compradores de Amazon recomiendan la funda de almohada de seda Mulberry, y está a la venta en este momento. La funda de almohada de seda viene en varios colores y ayuda a mantener el cabello suave y la piel clara. Compre las fundas de almohada de seda mientras tienen hasta un 46 por ciento de descuento en Amazon
El jueves se presentó una denuncia de delito menor amenazante agravado contra Joe Mixon.
El Departamento de Policía de Lafayette comenzó a investigar a un profesor de la Universidad de Purdue en diciembre después de recibir varias denuncias de un "hombre sospechoso que se acercaba a una mujer".
Al igual que el mundo que nos rodea, el lenguaje siempre está cambiando. Mientras que en eras anteriores los cambios en el idioma ocurrían durante años o incluso décadas, ahora pueden ocurrir en cuestión de días o incluso horas.
Estoy de vuelta por primera vez en seis años. No puedo decirte cuánto tiempo he estado esperando esto.
“And a river went out of Eden to water the garden, and from thence it was parted and became into four heads” Genesis 2:10. ? The heart is located in the middle of the thoracic cavity, pointing eastward.
Creo, un poco tarde en la vida, en dar oportunidades a la gente. Generosamente.