Nota para el moderador: resista la necesidad de editar el código o eliminar este aviso. El patrón de espacios en blanco puede ser parte de la pregunta y, por lo tanto, no debe ser manipulado innecesariamente. Si está en el campo "el espacio en blanco es insignificante", debería poder aceptar el código tal como está.
¿Es posible que se (a== 1 && a ==2 && a==3)
pueda evaluar true
en JavaScript?
Esta es una pregunta de entrevista realizada por una importante empresa de tecnología. Sucedió hace dos semanas, pero todavía estoy tratando de encontrar la respuesta. Sé que nunca escribimos ese código en nuestro trabajo diario, pero tengo curiosidad.
javascript
ecmascript-6
Dimpu Aravind Buddha
fuente
fuente
==
cuando quiera decir===
, tenga un estándar de codificación que prohíba nombres de variables que no sean ASCII y tenga un proceso de unión que refuerce las dos morales anteriores.Respuestas:
Si aprovecha cómo
==
funciona , podría simplemente crear un objeto con una función personalizadatoString
(ovalueOf
) que cambie lo que devuelve cada vez que se usa de modo que satisfaga las tres condiciones.La razón por la que esto funciona se debe al uso del operador de igualdad suelta. Cuando se utiliza la igualdad suelta, si uno de los operandos es de un tipo diferente al otro, el motor intentará convertir uno a otro. En el caso de un objeto a la izquierda y un número a la derecha, intentará convertir el objeto en un número llamando primero
valueOf
si es invocable y, en su defecto, llamarátoString
. Lo usétoString
en este caso simplemente porque es lo que se me ocurrió,valueOf
tendría más sentido. Si en cambio devolviera una cadenatoString
, el motor habría intentado convertir la cadena en un número que nos diera el mismo resultado final, aunque con una ruta un poco más larga.fuente
valueOf()
operación implícita ?valueOf
es un poco mejor.i
no molesta al motor. ;)No pude resistirme; las otras respuestas son indudablemente ciertas, pero realmente no puedes pasar el siguiente código:
Tenga en cuenta el espacio extraño en la
if
declaración (que copié de su pregunta). Es el Hangul de ancho medio (que es coreano para aquellos que no están familiarizados) que es un carácter de espacio Unicode que el script ECMA no interpreta como un carácter de espacio; esto significa que es un carácter válido para un identificador. Por lo tanto, hay tres variables completamente diferentes, una con el Hangul después de la a, otra con ella antes y la última con solo a. Reemplazando el espacio_
por legibilidad, el mismo código se vería así:Echa un vistazo a la validación en el validador de nombres de variables de Mathias . Si ese espacio extraño realmente se incluyó en su pregunta, estoy seguro de que es una pista para este tipo de respuesta.
No hagas esto. Seriamente.
Editar: Ha llegado a mi conocimiento que (aunque no se les permite iniciar una variable), el carpintero de ancho cero y cero-anchura no carpintería también están autorizados los caracteres en los nombres de variables - ver la ofuscación de JavaScript con ancho cero caracteres - pros y contras ? .
Esto se vería así:
fuente
var ᅠ2 = 3
se ha utilizado una variable ; así que están las tres variablesaᅠᅠ= 1, ᅠ2 = 3, a = 3
(a␣ = 1, ␣2 = 3, a = 3
, de modo que(a␣==1 && a==␣2 && a==3)
) ...¡ES POSIBLE!
Esto utiliza un captador dentro de una
with
declaración para permitira
evaluar tres valores diferentes.... esto todavía no significa que deba usarse en código real ...
Peor aún, este truco también funcionará con el uso de
===
.fuente
with
".with
no está permitido.with
lo que puede suceder==
. Y===
evita que la respuesta aceptada==
pero no he vistowith
desde ... bueno, en realidad nunca fuera de la documentación de JS donde dice "por favor no use eso". De todos modos, una buena solución.Ejemplo sin captadores o valueOf:
Esto funciona porque
==
invoca lotoString
que requiere.join
matrices.Otra solución, utilizando
Symbol.toPrimitive
cuál es un equivalente ES6 detoString/valueOf
:fuente
without valueOf
, bueno ... es más indirecto pero básicamente lo mismo.toString
o abuso,valueOf
pero esta me sorprendió por completo. Muy inteligente y no sabía que llamaba.join
internamente, pero tiene mucho sentido.Si se le pregunta si es posible (no DEBE), puede pedirle a "a" que devuelva un número aleatorio. Sería cierto si genera 1, 2 y 3 secuencialmente.
fuente
Cuando no puedes hacer nada sin expresiones regulares:
Funciona debido al
valueOf
método personalizado que se llama cuando Object se compara con primitivo (como Number). El truco principal es quea.valueOf
devuelve un nuevo valor cada vez porque llamaexec
a una expresión regular con ung
indicador, lo que provoca la actualizaciónlastIndex
de esa expresión regular cada vez que se encuentra una coincidencia. Entonces, la primera vezthis.r.lastIndex == 0
, coincide1
y se actualizalastIndex
:this.r.lastIndex == 1
así que la próxima vez la expresión regular coincidirá2
y así sucesivamente.fuente
exec
nuevamente comenzará a buscar desde ese índice. MDN no es muy claro.this.r
objeto regex recuerda el estado / índice. ¡Gracias!exec
, no un entero para ser stringificado.Se puede lograr utilizando lo siguiente en el ámbito global. Para
nodejs
usar englobal
lugar dewindow
en el código a continuación.Esta respuesta abusa de las variables implícitas proporcionadas por el alcance global en el contexto de ejecución definiendo un captador para recuperar la variable.
fuente
a
es una propiedad de lathis
que no parece ser. Sia
fuera una variable local (como se ve), entonces esto no funcionaría.a == 1
implica quea
es una variable en algún lugar, no una propiedad dethis
. Si bien hay un lugar extraño como los globales, donde ambos podrían ser ciertos, generalmente, declarar una variable convar a
olet a
significa que no hay ningunathis
que le permita accedera
como una propiedad como su código asume. Entonces, su código aparentemente está asumiendo algo extraño de variable global. Por ejemplo, su código no funciona en node.js y no en modo estricto dentro de una función. Debe especificar las circunstancias exactas donde funciona y probablemente explicar por qué funciona. De lo contrario, es engañoso.a
no es una variable local y se define en el ámbito global con un captador creciente.Esto es posible en el caso de que las variables
a
sean accedidas, digamos 2 trabajadores web a través de SharedArrayBuffer, así como algún script principal. La posibilidad es baja, pero es posible que cuando el código se compila en código máquina, los trabajadores web actualizan la variablea
justo a tiempo para que se cumplan las condicionesa==1
,a==2
ya==3
se satisfacen.Este puede ser un ejemplo de condición de carrera en un entorno de subprocesos múltiples proporcionado por los trabajadores web y SharedArrayBuffer en JavaScript.
Aquí está la implementación básica de lo anterior:
main.js
trabajador.js
modifier.js
En mi MacBook Air, sucede después de alrededor de 10 mil millones de iteraciones en el primer intento:
Segundo intento:
Como dije, las posibilidades serán bajas, pero dado el tiempo suficiente, llegará a la condición.
Sugerencia: si tarda demasiado en su sistema. Intenta solo
a == 1 && a == 2
y cambiaMath.random()*3
aMath.random()*2
. Agregar más y más a la lista reduce la posibilidad de golpear.fuente
Esto también es posible utilizando una serie de captadores de autoescritura:
(Esto es similar a la solución de jontro, pero no requiere una variable de contador).
fuente
===
, no solo==
.this
ser el objeto global dentro del cuerpo de la función de flecha.(a == 3 && a == 2 && a == 1)
?Alternativamente, puede usar una clase para ello y una instancia para la verificación.
EDITAR
Usar clases de ES6 se vería así
fuente
function A() {value = 0;
al principio?valueOf
se está anulando,this method is usually called automatically by JavaScript behind the scenes, and not explicitly in code
por lo que cuando comparamos el valor en realidad aumenta a ...No veo esta respuesta ya publicada, así que también incluiré esta en la mezcla. Esto es similar a la respuesta de Jeff con el espacio Hangul de ancho medio.
Puede notar una ligera discrepancia con el segundo, pero el primero y el tercero son idénticos a simple vista. Los 3 son caracteres distintos:
a
- Minúscula latina Aa
- Minúscula latina de ancho completo Aа
- Minúscula cirílica AEl término genérico para esto es "homoglifos": diferentes caracteres unicode que tienen el mismo aspecto. Por lo general, es difícil obtener tres que sean completamente indistinguibles, pero en algunos casos puedes tener suerte. A, Α, А, y Ꭺ funcionaría mejor (latín-A, alfa griega , cirílico-A , y Cherokee-A , respectivamente; por desgracia, el griego y Cherokee letras minúsculas son demasiado diferentes del latín
a
:α
,ꭺ
, y así doesn No ayudes con el fragmento anterior).Hay toda una clase de ataques de homoglifos, más comúnmente en nombres de dominio falsos (por ejemplo,
wikipediа.org
(cirílico) vswikipedia.org
(latino)), pero también puede aparecer en el código; normalmente se las conoce como poco claras (como se menciona en un comentario, las preguntas [poco claras] ahora están fuera de tema en PPCG , pero solían ser un tipo de desafío donde aparecían este tipo de cosas). Usé este sitio web para encontrar los homoglifos utilizados para esta respuesta.fuente
a
:a︀
a︁
a︂
. No más preocuparse por las discrepancias.¡Sí, es posible! 😎
»JavaScript
El código anterior es una versión corta (gracias a @Forivin por su nota en los comentarios) y el siguiente código es original:
»» C #
También escribí una versión de C # ( con una técnica de aumento del valor de la propiedad ):
Demo en vivo
fuente
if=()=>!0
document.write
? Esa es una forma segura de no ser contratado, independientemente del resto de la respuesta.console.log
pero la cambié a document.write. Realmente siempre lo usoconsole.log
en mis códigos, pero aquí solo quiero mostrar un texto a los usuarios en el cuadro de fragmentos de código de StackOverflow. Así que quería mostrar mi mensaje más hermoso que el mensaje generado porconsole.log
. Haga clic en elRun Code Snippet
botón en mi respuesta y en otras respuestas. El fragmento de código SO me permitió usar html y JS y CSS, luego quise usarlo en mi respuesta y hacerlo agradable. Creo que no tiene ningún efecto secundario negativo y no hizo que mi respuesta fuera grande o completa.JavaScript
a == a +1
En JavaScript, no hay enteros sino solo
Number
s, que se implementan como números de coma flotante de doble precisión.Significa que si un Número
a
es lo suficientemente grande, puede considerarse igual a tres enteros consecutivos:Es cierto, no es exactamente lo que preguntó el entrevistador (no funciona con
a=0
), pero no implica ningún truco con funciones ocultas o sobrecarga del operador.Otros idiomas
Como referencia, hay
a==1 && a==2 && a==3
soluciones en Ruby y Python. Con una ligera modificación, también es posible en Java.Rubí
Con una costumbre
==
:O un aumento
a
:Pitón
Java
Es posible modificar el
Integer
caché de Java :fuente
Integer a = 42
(o lo hace)? Según tengo entendido, el autoboxingInteger a = 42; a == 1 && a == 2 && a == 3
debería encuadrar todas las entradas. ¿O esto unbox un para las comparaciones?Integer == int
parece resultar en unboxing. Pero el uso deInteger#equals(int)
fuerzas autoboxing, por lo que funciona. ¡Gracias por el comentario!Numbers
en JS, que son básicamente comodouble
s. Pueden parecer enteros y puedes usarlos como enteros, pero aún no son enteros. No creo quen == n + 1
pueda ser cierto para los enteros en Java / Python / C / Ruby / ...Esta es una versión invertida de la respuesta de @ Jeff * donde se usa un carácter oculto (U + 115F, U + 1160 o U + 3164) para crear variables que se vean como
1
,2
y3
.* Esa respuesta se puede simplificar usando un ancho cero sin unión (U + 200C) y un ancho cero (U + 200D). Ambos caracteres están permitidos dentro de los identificadores, pero no al principio:
Son posibles otros trucos usando la misma idea, por ejemplo, usando selectores de variación Unicode para crear variables que se vean exactamente iguales (
a︀ = 1; a︁ = 2; a︀ == 1 && a︁ == 2; // true
).fuente
Regla número uno de entrevistas; Nunca digas imposible.
No hay necesidad de trucos de personajes ocultos.
fuente
__defineGetter__
en realidad no es parte del lenguaje js, solo una versión fea dedefineProperty
.typeof
no es una función y esto no declaradoi
es simplemente horrible. Todavía parece valer 40 votos a favor: /__defineGetter__
está en desuso por developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… pero se ejecuta claramente en mi FireFox v 57.0.4, así que opté por mostrar esto en lugar dedefineProperty()
porque el código heredado es real y no se puede ignorar. Independientemente de la fealdad, declarari
de la manera que lo hice es un comportamiento bien conocido / documentado. Tal vez solo estaba de humor PCG ¯ \ _ (ツ) _ / ¯Honestamente, sin embargo, si hay una forma de evaluarlo como verdadero o no (y como otros han demostrado, hay varias formas), la respuesta que estaría buscando, hablando como alguien que ha realizado cientos de entrevistas, sería algo en la línea de:
"Bueno, tal vez sí en un conjunto extraño de circunstancias que no son obvias para mí de inmediato ... pero si me encontrara con esto en un código real, usaría técnicas comunes de depuración para descubrir cómo y por qué estaba haciendo lo que estaba haciendo. e inmediatamente refactorizar el código para evitar esa situación ... pero lo más importante: NUNCA escribiría ese código en primer lugar porque esa es la definición misma de código contorneado, y me esfuerzo por nunca escribir código convolucionado ".
Supongo que algunos entrevistadores se ofenden por tener lo que obviamente debe ser una pregunta muy complicada, pero no me importa que los desarrolladores tengan una opinión, especialmente cuando pueden respaldarla con un pensamiento razonado y pueden encajar mi pregunta en Una declaración significativa sobre ellos mismos.
fuente
Si alguna vez recibe una pregunta de entrevista (o nota un comportamiento igualmente inesperado en su código) piense en qué tipo de cosas podrían causar un comportamiento que parece imposible a primera vista:
Codificación : en este caso, la variable que estás viendo no es la que crees que es. Esto puede suceder si intencionalmente juega con Unicode usando homoglifos o caracteres de espacio para hacer que el nombre de una variable se parezca a otra, pero los problemas de codificación también pueden introducirse accidentalmente, por ejemplo, al copiar y pegar código de la Web que contiene código Unicode inesperado puntos (p. ej., porque un sistema de gestión de contenido realizó un "formateo automático", como reemplazarlo
fl
con 'LATIN SMALL LIGATURE FL' (U + FB02) de Unicode).Condiciones de carrera : puede ocurrir una condición de carrera , es decir, una situación en la que el código no se ejecuta en la secuencia esperada por el desarrollador. Las condiciones de carrera a menudo suceden en código de subprocesos múltiples, pero no se requieren múltiples subprocesos para que las condiciones de carrera sean posibles: la asincronía es suficiente (y no se confunda, async no significa que se usen múltiples subprocesos debajo del capó ).
Tenga en cuenta que, por lo tanto, JavaScript tampoco está exento de condiciones de carrera solo porque es de un solo subproceso. Vea aquí un ejemplo simple de un solo subproceso, pero asíncrono. Sin embargo, en el contexto de una sola declaración, la condición de carrera sería bastante difícil de alcanzar en JavaScript.
JavaScript con los trabajadores web es un poco diferente, ya que puede tener múltiples hilos. @mehulmpt nos ha mostrado una gran prueba de concepto utilizando trabajadores web .
Efectos secundarios : un efecto secundario de la operación de comparación de igualdad (que no tiene que ser tan obvio como en los ejemplos aquí, a menudo los efectos secundarios son muy sutiles).
Este tipo de problemas puede aparecer en muchos lenguajes de programación, no solo en JavaScript, por lo que no estamos viendo uno de los clásicos WTF de JavaScript clásicos aquí 1 .
Por supuesto, la pregunta de la entrevista y las muestras aquí parecen muy artificiales. Pero son un buen recordatorio de que:
1 Por ejemplo, puede encontrar un ejemplo en un lenguaje de programación totalmente diferente (C #) que exhibe un efecto secundario (uno obvio) aquí .
fuente
Aquí hay otra variación, utilizando una matriz para extraer los valores que desee.
fuente
De acuerdo, otro truco con generadores:
fuente
this
ser el objeto de la ventana)Usando Proxies :
Los proxies básicamente pretenden ser un objeto de destino (el primer parámetro), pero interceptan operaciones en el objeto de destino (en este caso, la operación "obtener propiedad") para que haya una oportunidad de hacer algo que no sea el comportamiento predeterminado del objeto. En este caso, se activa la acción "obtener propiedad"
a
cuando==
coacciona su tipo para compararlo con cada número. Esto pasa:{ i: 0 }
, donde eli
propiedad es nuestro contadora
a ==
comparación,a
el tipo se coacciona a un valor primitivoa[Symbol.toPrimitive]()
internasa[Symbol.toPrimitive]
función usando el "get handler"Symbol.toPrimitive
, en cuyo caso se incrementa y luego devuelve el contador desde el objeto de destino:++target.i
. Si se recupera una propiedad diferente, simplemente volvemos a devolver el valor de propiedad predeterminado,target[name]
Entonces:
Como con la mayoría de las otras respuestas, esto solo funciona con una verificación de igualdad suelta (
==
), porque las verificaciones de igualdad estrictas (===
) no hacen una coerción de tipo que el Proxy puede interceptar.fuente
Symbol.toPrimitive
de la misma manera en un objeto funcionaría igual de bien.En realidad, la respuesta a la primera parte de la pregunta es "Sí" en todos los lenguajes de programación. Por ejemplo, esto es en el caso de C / C ++:
fuente
&&
lógico "y".Igual, pero diferente, pero igual (puede ser "probado" varias veces):
Mi idea comenzó de cómo funciona la ecuación de tipo de objeto Número.
fuente
Una respuesta ECMAScript 6 que hace uso de símbolos:
Debido al
==
uso, JavaScript se supone que coaccionana
en algo cerca del segundo operando (1
,2
,3
en este caso). Pero antes de que JavaScript intente calcular la coerción por sí solo, intenta llamarSymbol.toPrimitive
. Si proporcionaSymbol.toPrimitive
JavaScript, usaría el valor que devuelve su función. Si no, JavaScript llamaríavalueOf
.fuente
Creo que este es el código mínimo para implementarlo:
Crear un objeto ficticio con una costumbre
valueOf
que incremente una variable globali
en cada llamada. 23 personajes!fuente
¡Éste usa defineProperty con un agradable efecto secundario que causa una variable global!
fuente
a
:get: (a => () => ++a)(0),
no es necesario global.Al anular
valueOf
una declaración de clase, se puede hacer:Lo que sucede es que
valueOf
se llama en cada operador de comparación. En el primero,a
será igual1
, en el segundo,a
será igual2
, y así sucesivamente, porque cada vez quevalueOf
se llama, el valor dea
se incrementa.Por lo tanto, console.log se activará y generará (de todos modos en mi terminal)
Thing: { value: 4}
, lo que indica que el condicional era verdadero.fuente