Pregunta ¿Puede (a == 1 && a == 2 && a == 3) alguna vez evaluarse como verdadero?


Nota del moderador: Por favor, resista el impulso de editar el código o eliminar este aviso. El patrón de espacio en blanco puede ser parte de la pregunta y, por lo tanto, no debe manipularse innecesariamente. Si se encuentra en el campo "el espacio en blanco es insignificante", debería poder aceptar el código tal como está.

¿Es posible alguna vez que (a== 1 && a ==2 && a==3) podría evaluar a true en JavaScript?

Esta es una pregunta de entrevista hecha por una importante compañía 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.


2250
2018-01-15 20:20


origen


Respuestas:


Si aprovechas de cómo == trabajos, simplemente puedes crear un objeto con un diseño personalizado toString (o valueOf) función que cambia lo que devuelve cada vez que se utiliza de modo que satisfaga las tres condiciones.

const a = {
  i: 1,
  toString: function () {
    return a.i++;
  }
}

if(a == 1 && a == 2 && a == 3) {
  console.log('Hello World!');
}


El motivo por el que esto funciona se debe al uso del operador de igualdad loose. Cuando se utiliza 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 al llamar primero valueOf si es invocable y, si falla, llamará toString. solía toString en este caso, simplemente porque es lo que vino a la mente, valueOf tendría más sentido. Si, en cambio, devolviera una cadena de toString, el motor habría intentado convertir la cadena a un número que nos da el mismo resultado final, aunque con un camino un poco más largo.


3091
2018-01-15 20:35



No pude resistirme, las otras respuestas son indudablemente ciertas, pero realmente no puedes pasar el siguiente código:

var aᅠ = 1;
var a = 2;
var ᅠa = 3;
if(aᅠ==1 && a== 2 &&ᅠa==3) {
    console.log("Why hello there!")
}

Tenga en cuenta el espaciado extraño en el if declaración (que he copiado de su pregunta). Es el Hangul de ancho medio (que es coreano para los que no están familiarizados), que es un carácter de espacio Unicode que no es interpretado por el script ECMA 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 del a, otra con el anterior y la última con solo un. Reemplazando el espacio con _ para la legibilidad, el mismo código se vería así:

var a_ = 1;
var a = 2;
var _a = 3;
if(a_==1 && a== 2 &&_a==3) {
    console.log("Why hello there!")
}

Revisa la validación en el validador de nombre de variable de Mathias. Si ese espaciado extraño se incluyó realmente en su pregunta, estoy seguro de que es una pista para este tipo de respuesta.

No hagas esto Seriamente.

Editar: Me ha llamado la atención que (aunque no se permite iniciar una variable) el Carpintero de ancho cero y No-carpintero de ancho cero los caracteres también están permitidos en nombres de variables - ver Obfuscar JavaScript con caracteres de ancho cero - pros y contras?.

Esto se vería así:

var a= 1;
var a‍= 2; //one zero-width character
var a‍‍= 3; //two zero-width characters (or you can use the other one)
if(a==1&&a‍==2&&a‍‍==3) {
    console.log("Why hello there!")
}


1914
2018-01-16 05:14



¡ES POSIBLE!

var i = 0;

with({
  get a() {
    return ++i;
  }
}) {
  if (a == 1 && a == 2 && a == 3)
    console.log("wohoo");
}

Esto usa un getter dentro de un with declaración para dejar a evaluar a tres valores diferentes.

... esto todavía no significa que esto debería usarse en código real ...


565
2018-01-15 20:35



Ejemplo sin getters o valueOf:

a = [1,2,3];
a.join = a.shift;
console.log(a == 1 && a == 2 && a == 3);

Esto funciona porque == invoca toString que llamadas .join para Arrays.

Otra solución, usando Symbol.toPrimitive que es un equivalente de ES6 de toString/valueOf:

let a = {[Symbol.toPrimitive]: ((i) => () => ++i) (0)};

console.log(a == 1 && a == 2 && a == 3);


428
2018-01-17 11:37



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 de forma secuencial.

with({
  get a() {
    return Math.floor(Math.random()*4);
  }
}){
  for(var i=0;i<1000;i++){
    if (a == 1 && a == 2 && a == 3){
      console.log("after " + (i+1) + " trials, it becomes true finally!!!");
      break;
    }
  }
}


249
2018-01-16 06:21



Cuando no puedes hacer nada sin expresiones regulares:

var a = {
  r: /\d/g, 
  valueOf: function(){
    return this.r.exec(123)[0]
  }
}

if (a == 1 && a == 2 && a == 3) {
    console.log("!")
}

Funciona debido a la costumbre valueOf método que se llama cuando se compara Objeto con primitiva (como Número). El truco principal es que a.valueOf devuelve un nuevo valor cada vez porque está llamando exec en la expresión regular con g bandera, lo que causa la actualización lastIndex de esa expresión regular cada vez que se encuentre una coincidencia. Entonces primera vez this.r.lastIndex == 0, coincide 1 y actualizaciones lastIndex: this.r.lastIndex == 1, entonces la próxima vez que corresponda Regex 2 y así.


195
2018-01-16 19:35



Se puede lograr usando lo siguiente en el alcance global. por nodejs utilizar global en lugar de window en el código a continuación.

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 alcance global en el contexto de ejecución definiendo un getter para recuperar la variable.


183
2018-01-15 20:37