[javascript] (a == 1 && a == 2 && a == 3) 이제까지 true로 평가할 수 있습니까?

중재자 메모 : 코드를 편집하거나이 알림을 제거하려는 충동에 저항하십시오. 공백 패턴은 문제의 일부일 수 있으므로 불필요하게 변조해서는 안됩니다. “공백이 중요하지 않은”캠프에 있다면 코드를 그대로 받아 들일 수 있어야합니다.

그것은 가능성이 그 어느인가 (a== 1 && a ==2 && a==3)로 평가 할 수 true자바 스크립트로?

이것은 주요 기술 회사의 질문입니다. 그것은 2 주 전에 일어 났지만 여전히 답을 찾으려고 노력하고 있습니다. 나는 우리가 일상 생활에서 그런 코드를 쓰지 않는다는 것을 알고 있지만 궁금합니다.



답변

당신이 활용할 경우 어떻게 ==작동 , 당신은 단순히 정의와 객체 생성 할 수 있습니다 toString(또는 valueOf그것이 그게 만족 세 가지 조건 등 사용할 때마다 반환 무엇 변경) 기능.

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

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


이것이 작동하는 이유는 느슨한 동등 연산자를 사용하기 때문입니다. 느슨한 동등성을 사용할 때 피연산자 중 하나가 다른 유형과 다른 경우 엔진은 하나를 다른 것으로 변환하려고 시도합니다. 왼쪽에있는 객체와 오른쪽에있는 숫자의 valueOf경우, 호출 가능하면 먼저 호출 하여 호출하고 실패하면 호출 toString합니다. 나는 toString이 경우에 단순히 마음에 valueOf들었던 것이기 때문에 더 사용했다. 대신에서 문자열을 반환 toString하면 엔진은 문자열을 숫자로 변환하려고 시도했지만 경로가 약간 길지만 동일한 최종 결과를 제공합니다.


답변

나는 저항 할 수 없었다-다른 대답은 의심 할 여지없이 사실이지만, 다음 코드를 실제로 지나갈 수는 없다.

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

if명세서 에서 이상한 간격을 확인하십시오 (귀하의 질문에서 복사했습니다). ECMA 스크립트에서 공백 문자로 해석하지 않는 유니 코드 공백 문자 인 반자 한글 (익숙하지 않은 사용자에게는 한국어)입니다. 이는 식별자에 유효한 문자임을 의미합니다. 따라서 세 개의 완전히 다른 변수가 있습니다. 하나는 a 뒤에 한글이 있고 다른 하나는 앞에 a가 있고 마지막은 a가 있습니다. _가독성 을 위해 공백을 교체하면 동일한 코드는 다음과 같습니다.

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

Mathias의 변수 이름 validator에 대한 유효성 검사를 확인하십시오 . 그 이상한 간격이 실제로 그들의 질문에 포함되어 있다면, 나는 이것이 이런 종류의 대답에 대한 힌트라고 확신합니다.

이러지 마 진심으로.

편집 : 변수를 시작할 수는 없지만 너비0 인 조이너비 너비가 아닌 문자도 변수 이름에 허용 됩니다-너비가 0 인 문자로 JavaScript 난독 화-장단점 ? .

이것은 다음과 같습니다.

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!")
}


답변

것이 가능하다!

var i = 0;

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

이것은 with명령문 내부의 게터를 사용 a하여 세 가지 다른 값으로 평가할 수 있게 합니다.

… 여전히 이것이 실제 코드에서 사용해야한다는 의미는 아닙니다 …

더 나쁜 것은이 트릭을 사용하는 것입니다 ===.

  var i = 0;

  with({
    get a() {
      return ++i;
    }
  }) {
    if (a !== a)
      console.log("yep, this is printed.");
  }


답변

getter 또는 valueOf가없는 예 :

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

이것은 Arrays 를 호출 하기 때문에 작동 ==합니다 .toString.join

를 사용 Symbol.toPrimitive하는 또 다른 솔루션 은 다음과 같은 ES6입니다 toString/valueOf.

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

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


답변

가능한지 묻는다면 (필수 아님), “a”에게 임의의 숫자를 반환하도록 요청할 수 있습니다. 1, 2 및 3을 순차적으로 생성하면 사실입니다.

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;
    }
  }
}


답변

정규 표현식 없이는 아무것도 할 수없는 경우 :

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

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

valueOfObject가 Primitive와 비교할 때 호출되는 사용자 정의 메소드 (예 : Number) 때문에 작동합니다 . 주요 트릭은 플래그로 정규 표현식을 a.valueOf호출하기 때문에 매번 새로운 값 을 반환 하여 일치하는 모든 정규 표현식 이 업데이트 될 때마다 업데이트하는 것 입니다. 그래서 처음 에는 다음과 일치 하고 업데이트됩니다 . 따라서 다음 번에는 정규식이 일치 합니다.execglastIndexthis.r.lastIndex == 01lastIndexthis.r.lastIndex == 12


답변

전체 범위에서 다음을 사용하여 수행 할 수 있습니다. 위해 nodejs사용 global대신에 window아래의 코드이다.

var val = 0;
Object.defineProperty(window, 'a', {
  get: function() {
    return ++val;
  }
});
if (a == 1 && a == 2 && a == 3) {
  console.log('yay');
}

이 답변은 변수를 검색하기 위해 getter를 정의하여 실행 컨텍스트에서 전역 범위가 제공하는 암시 적 변수를 남용합니다.