Nota del moderador:** Por favor, resista el impulso de editar el código o eliminar este aviso. El patrón de los espacios en blanco puede ser parte de la cuestión y por lo tanto no debe ser manipulado innecesariamente. Si usted está en el "espacio en blanco es insignificante" campo, usted debe ser capaz de aceptar el código como es.
¿Es posible que (a== 1 && a ==2 && a==3)
pueda evaluarse como true
en JavaScript?
Esta es una pregunta de una 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 tipo de código en nuestro trabajo diario, pero tengo curiosidad.
Si aprovecha las ventajas de cómo funciona ==
, podría simplemente crear un objeto con una función personalizada toString
(o valueOf
) que cambie lo que devuelve cada vez que se utiliza de forma que satisfaga las tres condiciones.
begin snippet: js hide: false console: true babel: false -->
const a = {
i: 1,
toString: function () {
return a.i++;
}
}
if(a == 1 && a == 2 && a == 3) {
console.log('Hello World!');
}
La razón por la que esto funciona es el 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 en el 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 a valueOf
si se puede llamar, y si no, llamará a toString
. He utilizado toString
en este caso simplemente porque es lo que se me ha ocurrido, valueOf
tendría más sentido. Si en cambio devolviera una cadena desde toString
, el motor habría intentado convertir la cadena en un número dándonos el mismo resultado final, aunque con un camino un poco más largo.
¡ES POSIBLE!
begin snippet: js hide: false console: true babel: false -->
var i = 0;
with({
get a() {
return ++i;
}
}) {
if (a == 1 && a == 2 && a == 3)
console.log("wohoo");
}
Esto utiliza un getter dentro de una sentencia with
para que a
se evalúe a tres valores diferentes.
... esto todavía no significa que esto deba ser usado en código real...
Peor aún, este truco también funciona con el uso de ===
.
begin snippet: js hide: false console: true babel: false -->
var i = 0;
with({
get a() {
return ++i;
}
}) {
if (a !== a)
console.log("yep, this is printed.");
}
Se puede lograr usando lo siguiente en el ámbito global. Para nodejs
utilice global
en lugar de window
en el código siguiente.
begin snippet: js hide: false console: true babel: false -->
var val = 0;
Object.defineProperty(window, 'a', {
get: function() {
return ++val;
}
});
if (a == 1 && a == 2 && a == 3) {
console.log('yay');
}
Esta respuesta abusa de las variables implícitas proporcionadas por el ámbito global en el contexto de ejecución al definir un getter para recuperar la variable.