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


2484

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

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

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


9
의견은 긴 토론을위한 것이 아닙니다. 이 대화는 채팅 으로 이동 되었습니다 .
deceze

109
cloae에 너무 광범위 하다고 투표 한 사람들에게 : 자바 스크립트를 발굴하여 유효한 답변이 너무 많다고 말하는 것입니까?
초에 tomsmed

24
어떤 사람들은 가능한 것에 대해 철학적으로 앉아 있습니다. 다른 사람들은 고객을 위해 실행 가능한 비즈니스 올바른 제품을 구축하는지 여부에 초점을 맞추고 있습니다. IMO,이 질문은 인터뷰에서 이러한 종류의 질문을하거나 절대 이런 종류의 코드를 작성해서는 안된다는 사실을 넘어 실용성이 없습니다. 그것이 폐쇄되어야하는 이유입니다. 내 말은, 사업은 사람들이 앉아서이 물건에 대해 이야기하기 위해 실제 돈을 지불했음을 알고 있습니까?
P.Brian.Mackey

15
답을 읽은 후에 이야기의 도덕은 다음과 같습니다. ==당신이 의미 할 때 사용하지 말고 ===, ASCII가 아닌 변수 이름을 금지하는 코딩 표준을 가지고 있으며, 앞의 두 도덕을 강제하는 보푸라기 과정이 있습니다.
Jesse C. Slicer

87
진행자 주 : Stack Overflow는 사람들이 다른 언어로 답변을 해본 경험이 있습니다. 이것들 다른 언어로되어 있지만 일반적인 문제에 대한 해결책이기 때문에 질문에 대답하려는 시도입니다. "답이 아님"으로 표시하지 마십시오. 다른 언어로 더 많은 답변을 게시하지 마십시오.이 답변이 다른 답변 중 일부에서 주석으로 지적 된 것처럼 JavaScript에만 해당되는 이유가 있으며 언어 별 질문을 좋아하는 이유가 있습니다. 그렇게 남아 있습니다.
BoltClock

답변:


3323

당신이 활용할 경우 어떻게 ==작동 , 당신은 단순히 정의와 객체 생성 할 수 있습니다 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하면 엔진은 문자열을 숫자로 변환하려고 시도했지만 경로가 약간 길지만 동일한 최종 결과를 제공합니다.


70
묵시적 valueOf()조작 을 변경하여이를 달성 할 수 있습니까?
스털링 아처

43
예, valueOf 같은 이유로 된 toString 장소에서 작동
케빈 B

4
의견은 긴 토론을위한 것이 아닙니다. 이 대화는 채팅 으로 이동 되었습니다 .
deceze

13
에 따르면 번호 변환 그래서 먼저 시도한다 valueOf약간 더 좋다.
Salman A

6
@Pureferret 평등 비교의 왼쪽은 숫자가 아닌 객체입니다. 그 객체가 숫자 속성을 가지고 있다고 i엔진을 귀찮게하지 않습니다. ;)
tomsmeding

2057

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

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


368
원래 질문의 홀수 간격으로 판단하면, 이것은 공백과 같은 비 공백 문자를 악용하여 인터뷰 질문에서 찾은 정답이라고 생각합니다. 좋은 자리!
Baracus

18
@Baracus RonJohn은 Kevin의 답변에 대한 그의 의견에서 이상한 간격을 발견 하여이 (끔찍한) 기술을 상기 시켰기 때문에 그것을 발견 한 것에 대한 신용을 얻을 수 없었습니다. 어딘가에 블로그 포스트 때문에 몇 년 전 내 작업을 수행했기 때문에 아무도 이것에 대해 이미 대답하지 않은 것에 놀랐습니다. 지금은 꽤 일반적인 지식이라고 생각했습니다.
Jeff

102
물론 이것은 표준 허점으로 금지되어 있으며 인터뷰에도 적용됩니다. [인용 필요]
Sanchises

13
원래의 간격을 고려하면 더 나빠질 수 있습니다. 즉, 변수 var ᅠ2 = 3가 사용되었습니다. 그래서 세 가지 변수가 있습니다 aᅠᅠ= 1, ᅠ2 = 3, a = 3( a␣ = 1, ␣2 = 3, a = 3그래서, (a␣==1 && a==␣2 && a==3)...)
홀거

2
@ AL-zami 두 개의 변수에 여분의 문자가 있습니다.이 변수는 화면에 공백으로 표시되지만 식별자의 일부로 해석됩니다. 즉 , a, a 및 a-추가 문자는 한글 반자 공간
Jeff

620

것이 가능하다!

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.");
  }


65
그래, 난 같은 일을 시도하고 있었다 :) 인터뷰에서 정답이 될 것이다 그래서, "그것은 일어날 수없는 내가 사용하지 않기 때문에 코드 with."
Pointy

7
@Pointy- with허용되지 않는 엄격한 모드로 프로그램 합니다.
jfriend00

6
@Pointy 허용 된 답변에서 그들은 with일어날 수 있도록 비슷한 일을합니다
Jungkook

2
@jorrit 아무도 사용하지 않을 것입니다 ==. 그리고 ===허용 대답을 방지
조나스 윌름

4
@JonasW. 많은 사람들이 여전히 사용 ==하지만 그 with이후로는 보지 못했습니다 ... 실제로는 "사용하지 마십시오"라고 말하는 JS 문서 외부에서는 결코 사용하지 않았습니다. 어쨌든, 좋은 해결책.
wortwart

516

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


9
without valueOf글쎄 ... 더 간접적이지만 기본적으로 같은 것입니다.
Jonas Wilms

11
객체 자체 조인 기능 이외의 다른 것을 재정의하지 않기 때문에이 솔루션을 정말 좋아하며 논리를 참으로 평가하는 매우 깨끗하고 읽기 쉬운 해킹입니다.
Alex Pedersen

28
솔직히 이것이 최선의 대답이라고 생각합니다. 몇 가지 값만 설정하면 평범하지 않습니다. 기본적인 JS 지식으로도 이해하기 매우 쉽습니다. 잘 했어.
Zac Delventhal

14
이것은 거의 유용하다고 생각됩니다.
Andrew

7
나는 대부분의 답변 학대에 대한 줄 알았 toString또는 valueOf그러나이 사람은 가드에서 완전히 저를 붙 잡았다. 매우 영리하고 나는 그것이 .join내부적으로 전화 한 것을 몰랐지만 완전히 이해됩니다.
GBarroso

268

가능한지 묻는다면 (필수 아님), "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;
    }
  }
}


102
나는 다른 해결책을 알고 있더라도이 질문에 대답하지만 분명히 그 이후의 것이 아니기 때문에 의도적 으로이 대답을 줄 것입니다. 바보 같은 게임을하고 바보 같은 상을 받으세요.
ESR

2
그러나 1000 회 이상의 시험이 필요한 경우 어떻게해야합니까?
Piyin

9
@Piyin 1000 회 이상의 평가판이 필요한 경우 상을받습니다!
스키트

5
이 답변처럼 나는 극단적으로 복용이 가능한 것을 알 수 있기 때문에 어떤 프로그램이 실행되는 동안 CPU의 레지스터 / 충분히 우주 광선에 치여 캐시 경우 언어, 또는 하나는 의도적으로 실패 지점의 같은 전원 글리치를 수행하는 경우 if 조건이 실제로 점프하지 않습니다.
Ponkadoodle

최저 : 1, 최고 : 412.
KyleFairns 10

210

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

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


22
@Abdillah 정규식 객체는 일치하는 마지막 색인을 기억하고 exec다시 호출 하면 해당 색인에서 검색을 시작합니다. MDN 은 명확하지 않습니다.
Simon Chan

나는 this.r정규식 객체가 상태 / 색인을 기억한다는 것을 알았다 . 감사!
Abdillah

문자열 exec화 할 정수가 아닌 문자열을 전달하는 것이 좋습니다 .
Bergi

정규 표현식을 사용하면 이제 두 가지 문제가 있습니다.
Aleksey Solovey

191

전체 범위에서 다음을 사용하여 수행 할 수 있습니다. 위해 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를 정의하여 실행 컨텍스트에서 전역 범위가 제공하는 암시 적 변수를 남용합니다.


이것은 보이지 않는 a속성 이라고 가정 this합니다. 경우 a다음이 작동하지 않을 것입니다 (이 모양) 로컬 변수를했다.
jfriend00

1
@ jfriend00 당신은 var a를 배치했다는 것을 의미합니다. 어딘가에?
jontro

네. 참조 는의 속성이 아닌 어딘가에있는 변수를 a == 1의미합니다 . 전역과 같이 둘 다 참일 수있는 이상한 곳이 있지만 일반적으로 변수를 선언 하거나 의미 하는 것은 코드가 가정하는 것처럼 속성으로 액세스 할 수 없다는 것 입니다 . 따라서 코드는 이상한 전역 변수를 가정하고 있습니다. 예를 들어, 코드는 node.js에서 작동하지 않으며 함수 내부의 엄격 모드에서는 작동하지 않습니다. 작동하는 정확한 환경을 지정하고 작동 이유를 설명해야합니다. 그렇지 않으면 오도의 소지가 있습니다. athisvar alet athisa
jfriend00

@ jfriend00 물론입니다. 이미 다른 답변과 함께 더 많은 가치를 추가 할 것인지 확실하지 않습니다. 답변을 업데이트 할 것입니다
jontro

14
문제는 이것이 "언제나"사실 일 수 있는가하는 것이었다. 그리고 대답은 그렇습니다. 이것이 사실 일 수있는 시나리오 중 하나입니다 a. 지역 변수가 아니며 증가하는 getter를 사용하여 전역 범위에서 정의됩니다.
Zac Delventhal

190

이것은 a2 개의 웹 작업자가 SharedArrayBuffer 및 일부 주요 스크립트를 통해 변수 에 액세스하는 경우 가능합니다 . 가능성은 낮지 만 코드를 기계어 코드로 컴파일 할 때, 웹 노동자 변수를 업데이트하는 것이 가능하다 a단지 조건 때문에 시간에 a==1, a==2그리고 a==3만족하고 있습니다.

이것은 웹 워커와 JavaScript의 SharedArrayBuffer가 제공하는 멀티 스레드 환경에서 경쟁 조건의 예일 수 있습니다.

위의 기본 구현은 다음과 같습니다.

main.js

// Main Thread

const worker = new Worker('worker.js')
const modifiers = [new Worker('modifier.js'), new Worker('modifier.js')] // Let's use 2 workers
const sab = new SharedArrayBuffer(1)

modifiers.forEach(m => m.postMessage(sab))
worker.postMessage(sab)

worker.js

let array

Object.defineProperty(self, 'a', {
  get() {
    return array[0]
  }
});

addEventListener('message', ({data}) => {
    array = new Uint8Array(data)
    let count = 0
    do {
        var res = a == 1 && a == 2 && a == 3
        ++count
    } while(res == false) // just for clarity. !res is fine
    console.log(`It happened after ${count} iterations`)
    console.log('You should\'ve never seen this')
})

modifier.js

addEventListener('message' , ({data}) => {
    setInterval( () => {
        new Uint8Array(data)[0] = Math.floor(Math.random()*3) + 1
    })
})

MacBook Air에서 첫 번째 시도에서 약 100 억 회 반복 된 후에 발생합니다.

여기에 이미지 설명을 입력하십시오

두 번째 시도 :

여기에 이미지 설명을 입력하십시오

내가 말했듯이, 기회는 적지 만 충분한 시간이 주어지면 조건에 부딪 칠 것입니다.

팁 : 시스템에 시간이 너무 오래 걸리는 경우 시도 만하고로 a == 1 && a == 2변경 Math.random()*3하십시오 Math.random()*2. 목록에 점점 더 추가하면 타격 가능성이 줄어 듭니다.


50
솔직히 이것은 최선의 대답입니다. 다른 모든 대답에는 깊이 직관적이지 않은 일을하려는 의도적 인 시도가 필요합니다. 이 답변은 실제로 실제 상황에서 발생할 수있는 무언가, 즉 경쟁 조건을 반영합니다.
Tom Swirly

34
뿐만 아니라-나는 이것이 실제로 현실에서 일어나는 것을 보았습니다. 문제의 정확한 조건이 아니라 함수 시작시 (a == 1) 및 함수 후반에 (a == 2) 확인하고 코드가 두 조건에 모두 맞아야합니다. 참고로, 처음이 일이 자동차 엔진 컨트롤러에 있었을 때 코딩 표준을 적용했습니다. 두 번째는 군용 항공기 용 쉐프 및 플레어 디스펜서 시스템에 있었고 회사에서 첫날 나는 이것을 발견하고 수정했지만 나머지 팀은 여전히 ​​문제를 논의했습니다. (쿠도 레벨 : 높음! :)
Graham

38
웹 작업자와 함께 자바 스크립트로 프로그래밍 된 "자동차 엔진 컨트롤러"및 "채프 및 플레어 디스펜서 시스템"에 대해 작업 했습니까? 다시 밖에 나가지 않을 것 같아요.
psaxton

12
@psaxton :) 물론 아닙니다. 그러나 공유 데이터가있는 멀티 스레드 소프트웨어가 있습니다. 이것은 자바 스크립트 나 웹 워커에만 국한되지 않는 모든 멀티 스레드 소프트웨어의 안티 패턴입니다. 어셈블리 언어, Brainf * ck, Visual BASIC, C 또는 Javascript로 프로그래밍하는지 여부는 중요하지 않습니다. 다중 스레드 응용 프로그램에서 공유 데이터로이 작업을 수행 하면 항상 실패합니다.
Graham

4
나는 이것이 @jontro의 대답을 둘러싼 정교한 포장지라고 생각합니다.
qntm

148

이것은 일련의 자체 덮어 쓰기 게터를 사용하여 가능합니다.

(이것은 jontro의 솔루션과 유사하지만 카운터 변수가 필요하지 않습니다.)

(() => {
    "use strict";
    Object.defineProperty(this, "a", {
        "get": () => {
            Object.defineProperty(this, "a", {
                "get": () => {
                    Object.defineProperty(this, "a", {
                        "get": () => {
                            return 3;
                        }
                    });
                    return 2;
                },
                configurable: true
            });
            return 1;
        },
        configurable: true
    });
    if (a == 1 && a == 2 && a == 3) {
        document.body.append("Yes, it’s possible.");
    }
})();


61
게터를 사용하는 방법도 함께 작동합니다 ===뿐만 아니라, ==.
Makyen

이 솔루션은 this화살표 함수 본문 내부의 전역 객체 에 의존 합니다.
Roy Tinker

@Midnightas 나는 다른 답변을 "피라미드 코드" 로 분류하지 않을 것 입니다.
Patrick Roberts

이것은 임의의 순서로도 작동합니다. 처럼 (a == 3 && a == 2 && a == 1)?
Johannes

131

또는 클래스를 사용하고 검사를 위해 인스턴스를 사용할 수 있습니다.

function A() {
    var value = 0;
    this.valueOf = function () { return ++value; };
}

var a = new A;

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

편집하다

ES6 클래스를 사용하면 다음과 같습니다.

class A {
  constructor() {
    this.value = 0;
    this.valueOf();
  }
  valueOf() {
    return this.value++;
  };
}

let a = new A;

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


5
단지 function A() {value = 0;시작에?
Dave C

valueOf재정의되고 this method is usually called automatically by JavaScript behind the scenes, and not explicitly in code있으므로 값을 비교할 때 실제로 증가합니다 ..
Danyal Sandeelo

130

이 답변이 이미 게시되어 있지 않으므로이 답변을 믹스에 넣을 것입니다. 이것은 반자 한글 공간에 대한 Jeff의 대답 과 비슷 합니다.

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

두 번째 것과 약간의 차이가있을 수 있지만 첫 번째와 세 번째는 육안과 동일합니다. 3 개 모두 고유 한 문자입니다.

a-라틴 소문자 A-
전각 라틴 소문자 A-
а키릴 소문자 A

이에 대한 일반적인 용어는 "상형 문자"입니다. 다른 유니 코드 문자는 동일하게 보입니다. 일반적으로 완전히 구분할 수없는 3 가지 를 구하기 는 어렵지만 경우에 따라 운이 좋을 수도 있습니다. A, Α는, А 및 Ꭺ이 더 잘 작동 것 (라틴-A는 그리스어 알파 , 키릴-A , 그리고 체로키-A , 각각 불행하게도 그리스와 체로키 소문자는 라틴어에서 너무 다르다 a: α, , 및 아무튼 그래서 위의 스 니펫에는 도움이되지 않습니다).

가짜 도메인 이름 (예 : wikipediа.org(Cyrillic) vs wikipedia.org(Latin)) 에서 가장 일반적으로 Homoglyph Attacks의 전체 클래스가 있지만 코드에도 나타날 수 있습니다. 일반적으로 불완전한 것으로 언급됩니다 (의견에서 언급 한 바와 같이, [언더 나드 ] 질문은 이제 PPCG 에 대한 주제가 아니지만 이러한 종류의 것들이 나타나는 도전의 유형이었습니다). 내가 사용하는 이 웹 사이트를 이 답변에 사용되는 호모 글리프를 찾을 수 있습니다.


19
"약간의 불일치" 는 내가 그렇게 부르는 방법이 아닙니다.

4
@hvd 글꼴 렌더링에 전적으로 의존합니다. 이것이 내가 보는 것 입니다.
Draco18s는 더 이상 SE

1
@Jake 예, 전각 라틴어 소문자 A는 가장 큰 상형 문자는 아니지만 대문자 문자 변형은 훌륭합니다. 일반적으로 원하는 효과를 얻으려면 두 개만 있으면됩니다.
Draco18s는 더 이상 SE

@ Draco18s 합의 re : 보통 2 개만 필요합니다. 추가 정보도 잘하셨습니다!
JakeSteam

10
유니 코드 변형 선택기 (U + FE00..U + FE0F)를 사용할 수도 있습니다. 이들 중 어느 것도 a: a︀ a︁ a︂. 불일치에 대해 더 이상 걱정하지 않아도됩니다.
살만 A

108

네 가능합니다! 😎

»자바 스크립트

if‌=()=>!0;
var a = 9;

if‌(a==1 && a== 2 && a==3)
{
    document.write("<h1>Yes, it is possible!😎</h1>")
}

위의 코드는 짧은 버전이며 (주석에주의를 기울여 @Forivin 덕분에) 다음 코드는 독창적입니다.

var a = 9;

if‌(a==1 && a== 2 && a==3)
{
    //console.log("Yes, it is possible!😎")
    document.write("<h1>Yes, it is possible!😎</h1>")
}

//--------------------------------------------

function if‌(){return true;}

내 코드의 상단을보고 실행하면 WOW라고 말하면 어떻게됩니까?

내가 말할 정도로 생각 그래서 네, 가능 당신에게 말했다 사람에게 : 아무것도 불가능

속임수 : 숨겨진 if이름을 사용하여 그 이름과 비슷한 기능을했습니다 if. JavaScript에서는 키워드를 재정의 할 수 없으므로이 방법을 사용해야했습니다. 그것은 가짜 if이지만이 경우에는 효과가 있습니다!


» C #

또한 C # 버전을 작성했습니다 ( 속성 값 technic 증가 ).

static int _a;
public static int a => ++_a;

public static void Main()
{
    if(a==1 && a==2 && a==3)
    {
        Console.WriteLine("Yes, it is possible!😎");
    }
}

라이브 데모


56
자바 스크립트 버전은 인류에 대한 진정한 범죄이며이를 수행하는 능력은 UN 협약에 의해 불법이어야합니다. 나는 우리가 javacript에 대한 모든 지식의 세계를 정화 할 시간이라고 생각합니다.
더 명확한

2
함수 선언은 더 짧을 수 있습니다. if‌=()=>!0
Forivin

4
왜 지구상에서 사용 document.write했습니까? 그것은 나머지 답변에 관계없이 고용되지 않는 확실한 방법입니다.
Cerbrus

3
@Cerbrus, 감사합니다. 먼저 답변을 console.log썼지 만 document.write로 변경했습니다. 실제로 항상 console.log코드에서 사용 하지만 여기서는 StackOverflow 코드 스 니펫 상자에 사용자에게 텍스트를 표시하고 싶습니다. 에 의해 생성 된 메시지보다 더 아름다운 메시지를 보여주고 싶었습니다 console.log. Run Code Snippet내 답변과 다른 답변에 있는 버튼을 클릭하십시오 . SO 코드 스 니펫을 사용하면 html과 JS 및 CSS를 사용할 수 있으며 대답에 사용하고 멋지게 만들고 싶었습니다. 나는 부작용이 없으며 내 대답을 크게 만들거나 생각하지 않았다고 생각합니다.
RAM

1
@Clearer, UN- 컨벤션이 세계를 효과적으로 바꿀 수 있다면 우리는 이보다 더 나은 세상을 가져야합니다. 우리는 UN과 나는 우리가 내이 자바 스크립트 트릭을 사용할 수 있습니다 생각이 날 때까지 문보다 더 많은 일도 필요)
RAM

97

자바 스크립트

a == a +1

JavaScript에는 정수가 없지만 Numbers 만 배정도 부동 소수점 숫자로 구현됩니다.

이는 Number a가 충분히 큰 경우 3 개의 연속 정수와 같은 것으로 간주 될 수 있음을 의미합니다 .

a = 100000000000000000
if (a == a+1 && a == a+2 && a == a+3){
  console.log("Precision loss!");
}

사실, 면접관이 요청한 것과 정확히 일치하지는 않지만 ( a=0숨겨지지 않음) 숨겨진 기능이나 연산자 오버로드와 관련된 트릭은 포함되지 않습니다.

다른 언어

참고 a==1 && a==2 && a==3로 Ruby와 Python 에는 솔루션 이 있습니다 . 약간만 수정하면 Java에서도 가능합니다.

루비

관습으로 ==:

class A
  def ==(o)
    true
  end
end

a = A.new

if a == 1 && a == 2 && a == 3
  puts "Don't do this!"
end

또는 증가 a:

def a
  @a ||= 0
  @a += 1
end

if a == 1 && a == 2 && a == 3
  puts "Don't do this!"
end

파이썬

class A:
    def __eq__(self, who_cares):
        return True
a = A()

if a == 1 and a == 2 and a == 3:
    print("Don't do that!")

자바

Java Integer캐시 를 수정할 수 있습니다 .

package stackoverflow;

import java.lang.reflect.Field;

public class IntegerMess
{
    public static void main(String[] args) throws Exception {
        Field valueField = Integer.class.getDeclaredField("value");
        valueField.setAccessible(true);
        valueField.setInt(1, valueField.getInt(42));
        valueField.setInt(2, valueField.getInt(42));
        valueField.setInt(3, valueField.getInt(42));
        valueField.setAccessible(false);

        Integer a = 42;

        if (a.equals(1) && a.equals(2) && a.equals(3)) {
            System.out.println("Bad idea.");
        }
    }
}

27
@ cᴏʟᴅsᴘᴇᴇᴅ : Java, Javascript, potayto, potahto :) 이미 좋은 JS 답변이 충분합니다. 방금 다른 언어로 어떻게 할 수 있는지 보여주고 JS 개발자에게 아이디어를 줄 수 있다는 것이 흥미로울 것이라고 생각했습니다.
Eric Duminil

2
@ cᴏʟᴅsᴘᴇᴇᴅ : JS 예제로 업데이트되었습니다.
Eric Duminil

1
Java 버전이 작동하지 않는 이유는 무엇 Integer a = 42입니까? 내가 오토 박싱을 이해함에 따라 Integer a = 42; a == 1 && a == 2 && a == 3모든 정수를 박스 에 넣어야한다. 아니면 비교를 위해 박스를 개봉합니까?
CAD97

@ CAD97 : 상자가 열리지 않는 Integer == int것 같습니다. 그러나 자동 상자 사용을 사용 Integer#equals(int)하면 작동합니다. 의견 주셔서 감사합니다!
Eric Duminil

@StephanBijzitter : 설명해주세요. 내가 아는 Numbers한 JS에는 기본적으로 doubles 와 같은 것이 있습니다. 정수처럼 보일 수 있고 정수처럼 사용할 수 있지만 여전히 정수는 아닙니다. n == n + 1Java / Python / C / Ruby /의 정수에 대해서는 사실 이라고 생각하지 않습니다 .
Eric Duminil

80

이것은 @Jeff의 답변의 역 버전입니다. 숨겨진 문자 (U + 115F, U + 1160 또는 U + 3164)가 같은 표정 변수를 만드는 데 사용됩니다 * 1, 2하고 3.

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

* 폭이 0이 아닌 조이너 (U + 200C) 및 폭이 0 인 조이너 (U + 200D)를 사용하면이 답변을 단순화 할 수 있습니다. 이 두 문자는 식별자 내부에서 허용되지만 처음에는 사용할 수 없습니다.

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

/****
var a = 1;
var a\u200c = 2;
var a\u200d = 3;
console.log(a == 1 && a\u200c == 2 && a\u200d == 3);
****/

동일한 아이디어를 사용하는 것과 같은 다른 트릭도 가능합니다 (예 : 유니 코드 변형 선택기를 사용하여 정확히 똑같이 보이는 변수 생성 a︀ = 1; a︁ = 2; a︀ == 1 && a︁ == 2; // true).


75

인터뷰 규칙 1 번; 불가능하다고 말하지 마십시오.

숨겨진 캐릭터 속임수가 필요하지 않습니다.

window.__defineGetter__( 'a', function(){
    if( typeof i !== 'number' ){
        // define i in the global namespace so that it's not lost after this function runs
        i = 0;
    }
    return ++i;
});

if( a == 1 && a == 2 && a == 3 ){
    alert( 'Oh dear, what have we done?' );
}


6
아야. __defineGetter__실제로 js 언어의 일부가 아닌 추한 버전입니다 defineProperty. typeof함수가 아니며 선언되지 않은 i것은 단지 끔찍합니다. 여전히 40 개의 공감 가치가있는 것 같습니다 : /
Jonas Wilms

6
@JonasW. 41 upvotes :-) developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…에서__defineGetter__ 더 이상 사용되지 않는다는 것을 알고 있지만 FireFox v 57.0.4에서 명확하게 실행되므로 대신에 이것을 표시하도록 선택했습니다. 레거시 코드는 실제 코드이므로 무시할 수 없기 때문입니다. 추악함에 관계없이 내가 한 방식으로 선언 하는 것은 잘 알려진 / 문서화 된 행동입니다. 어쩌면 나는 PCG 분위기에 있었을 것입니다 ¯ \ _ (ツ) _ / ¯defineProperty()i
MonkeyZeus

68

솔직히 말해서 그것이 참으로 평가 될 수있는 방법이 있는지 아닌지 (그리고 다른 사람들이 보여 주었 듯이 여러 가지 방법이 있습니다), 수백 번의 인터뷰를 한 사람으로서 말하고 싶은 대답은 라인을 따라 뭔가 :

"음, 아마 나에게 명백하지 않은 이상한 상황에서 그렇습니다.하지만 실제 코드에서이 문제가 발생하면 일반적인 디버깅 기술을 사용하여 어떻게 그리고 왜 그 일을하고 있었는지 알아낼 것입니다. 그런 다음 상황을 피하기 위해 즉시 코드를 리팩터링합니다 ... 그러나 더 중요한 것은 : 코드가 매우 복잡한 코드의 정의이기 때문에 절대로 코드를 처음에는 절대 작성하지 않을 것입니다.

일부 면접관은 매우 까다로운 질문이라고 생각되는 것을 갖는 것에 화를 낼 것이라고 생각하지만, 의견을 가진 개발자, 특히 그들이 합리적인 생각으로 그것을 뒷받침 할 수 있고 내 질문을 받아 들일 수있는 개발자는 신경 쓰지 않습니다. 자신에 대한 의미있는 진술.


13
질문 (또는 모든 인터뷰 질문)은 문제, 특히 이와 같이 "명백하게 명백한"문제에 대해 기꺼이 생각하는 후보자를 테스트하는 것입니다. 그들이 "답을"알고 있다고 생각하기 때문에 생각을 거부하는 사람은 좋은 고용이 아닙니다.
Shammoo

5
@ 돈 해치 아니, 나는 그들이 선의로 대답하고 특히 다른 사람들이 보여준 것과 같은 정답을 주었다면 그들을 처벌하지 않을 것입니다 ... 그러나 나는 그들이 후속 생각을하는지 조사하도록 요청할 것입니다. 코드를 작성하는 좋은 방법입니다. 지식이 풍부하고 "올바른"답변을 얻을 수 있다는 것은 좋은 개발자가되는 것의 일부일뿐입니다. "전문적인"개발자에게는 훨씬 더 중요한 것은 능력이 부족한 개발자가 종종 이해하고 유지 보수 할 수있는 코드를 작성하는 것입니다. 지나치게 영리한 개발자는 능력이없는 IME만큼 나쁘다.
Frank W. Zammetti

16
이것은 질문에 대답하지 않습니다.
TylerH

6
이 답변에 대한 슬픈 점은 1rep 사용자가 어제 그 대답을했고이 질문을 삭제하도록 2 개의 다운 보트를 받았다는 것입니다.
Jonas Wilms

8
@ JohnColeman 질문은 코드가 참으로 평가되는 방법을 묻습니다. 면접관이 먼저 질문을 제안한 이유는 묻지 않습니다. 이 답변은 요청 된 질문을 다루려고 시도하지 않으며, 대신 인터뷰 자의 목적이 무엇인지 추측하려는 시도의 "내가하려는 것"버전에 전적으로 초점을 맞 춥니 다. 그것이 질문이라면, 그것은 너무 광범위 할 것입니다. 따라서이 답변은 여기 또는 사이트의 어느 곳에도 속하지 않습니다.
TylerH

43

그러한 인터뷰 질문을 받거나 코드에서 예상치 못한 행동을 발견하면 언뜻보기에는 불가능한 행동을 일으킬 수있는 것들에 대해 생각하십시오.

  1. 인코딩 :이 경우보고있는 변수는 생각한 변수가 아닙니다. 변수 이름을 다른 문자 처럼 보이게하기 위해 동종 문자 또는 공백 문자 를 사용하여 의도적으로 유니 코드로 엉망이 될 수 있지만 예기치 않은 유니 코드 코드가 포함 된 웹에서 코드를 복사하여 붙여 넣을 때 인코딩 문제가 실수로 발생할 수 있습니다. 콘텐츠 관리 시스템이 fl유니 코드 'LATIN SMALL LIGATURE FL'(U + FB02) 로 대체 하는 등의 "자동 서식 지정"을 수행했기 때문 입니다.

  2. 경쟁 조건 : 경쟁 조건 , 즉 개발자가 예상 한 순서대로 코드가 실행되지 않는 상황이 발생할 수 있습니다. 경쟁 조건은 종종 멀티 스레드 코드에서 발생하지만 경쟁 조건이 가능하기 위해서는 여러 스레드가 필요하지 않습니다. 비동기 성이 충분합니다 (혼동 하지 마십시오. 비동기는 여러 스레드가 후드 아래에서 사용됨을 의미하지는 않습니다) ).

    따라서 JavaScript는 단일 스레드이기 때문에 경쟁 조건에서 자유롭지 않습니다. 여기를 참조 하십시오간단한 단일 스레드이지만 비동기 예제는 를 . 그러나 단일 문장의 맥락에서 경쟁 조건은 JavaScript에서 다루기가 다소 어려울 것입니다.

    웹 작업자가있는 JavaScript는 여러 스레드를 가질 수 있으므로 약간 다릅니다. @mehulmpt는 웹 작업자를 사용하여 훌륭한 개념 증명 을 보여주었습니다 .

  3. 부작용 : 평등 비교 연산의 부작용 (여기의 예에서와 같이 명확 할 필요는 없지만 종종 부작용은 매우 미묘합니다).

이러한 종류의 문제는 JavaScript뿐만 아니라 많은 프로그래밍 언어로 나타날 수 있으므로 여기서는 전형적인 JavaScript WTF 중 하나가 보이지 않습니다 1 .

물론 인터뷰 질문과 샘플은 모두 매우 고안된 것처럼 보입니다. 그러나 그들은 다음을 잘 기억합니다.

  • 부작용은 실제로 불쾌 할 수 있으며 잘 설계된 프로그램에는 원하지 않는 부작용이 없어야합니다.
  • 멀티 스레딩 및 변경 가능한 상태는 문제가 될 수 있습니다.
  • 문자 인코딩 및 문자열 처리 권한을 수행하지 않으면 버그가 발생할 수 있습니다.

1 예를 들어, 부작용 (명백한 것)을 나타내는 완전히 다른 프로그래밍 언어 (C #)에서 예제를 찾을 수 있습니다 .


1
그러면 질문이 너무 광범위 해집니다. 다양한 언어로 다양한 수준으로 쉽게 구현할 수 있습니다. 질문은 JS 특정 Q & A이기 때문에 많은 관심을 얻었습니다. 그러나 그것은 단지 2c입니다.
cs95

1
원인은 다른 C #과 자바 스크립트 이므로이 대답은 합법적이지 않습니다.
Edwin

3
@ Edwin : 그 원인은 정확히 동일합니다 : 비슷한 모양의 그림 문자 또는 공백 문자, 경쟁 조건 또는 비교 작업의 부작용 (후자는 내 예제에 표시됨)을 사용하는 유니 코드입니다.
Dirk Vollmar

2
@ cᴏʟᴅsᴘᴇᴇᴅ : 때로는 더 넓은 각도에서 사물을 보면 실제 문제를 보는 데 도움이됩니다.
Dirk Vollmar

3
이 답변이 "meta"방식으로이 질문에 태그되기를 바랍니다. 위의 모든 답변을 읽은 후 JS에 너무 많은 구멍이있는 것처럼 느껴졌지만 한 번에 모든 답변을 요약했습니다. 그리고 당신은 이것을 내 의견으로는 이것을 훌륭한 인터뷰 질문 (언어 별 태그가 제거 된 경우)으로 만드는 방식으로했습니다. 브라보!
KCE

41

다음은 배열을 사용하여 원하는 값을 표시하는 또 다른 변형입니다.

const a = {
  n: [3,2,1],
  toString: function () {
    return a.n.pop();
  }
}

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


31

좋아, 발전기로 또 다른 해킹 :

const value = function* () {
  let i = 0;
  while(true) yield ++i;
}();

Object.defineProperty(this, 'a', {
  get() {
    return value.next().value;
  }
});

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


당신은 해킹 말하지만, 난 확신이 발전기의 사용 사례 (이에 의존하는 것을 제외하고, 잘 ... :)입니다 thiswindow 객체 인)
코디 G

29

프록시 사용 :

var a = new Proxy({ i: 0 }, {
    get: (target, name) => name === Symbol.toPrimitive ? () => ++target.i : target[name],
});
console.log(a == 1 && a == 2 && a == 3);

프록시는 기본적으로 대상 개체 인 것처럼 가장하지만 기본 개체 동작 이외의 작업을 수행 할 수 있도록 대상 개체에 대한 작업 (이 경우 "get 속성"작업)을 가로 챌 수 있습니다. 이 경우 "get property"조치는 각 숫자와 비교하기 위해 해당 유형을 강제 a할 때 호출됩니다 ==. 이것은 일어난다 :

  1. 대상 객체를 만듭니다 { i: 0 }.i 속성은 우리의 카운터
  2. 대상 객체에 대한 프록시를 생성하여 a
  3. a ==비교에 대해a 의 유형은 기본 값으로 강제 변환됩니다.
  4. 이 유형의 강제는 a[Symbol.toPrimitive]() 내부적
  5. 프록시는 a[Symbol.toPrimitive] 는 "get handler"를 사용하여 함수 합니다.
  6. Proxy의 "get handler"는 가져 오는 속성이 확인하고, Symbol.toPrimitive이 경우 증가하고 대상 객체에서 카운터를 반환합니다 ++target.i. 다른 속성을 검색하는 경우 기본 속성 값을 반환하는 것으로 넘어갑니다.target[name]

그래서:

var a = ...; // a.valueOf == target.i == 0
a == 1 && // a == ++target.i == 1
a == 2 && // a == ++target.i == 2
a == 3    // a == ++target.i == 3

대부분의 다른 답변과 마찬가지로 ==엄격한 동등 검사 ( ===)는 프록시가 가로 챌 수있는 유형 강제 변환을 수행하지 않기 때문에 느슨한 동등 검사 ( ) 에서만 작동합니다 .


2
그러나이를 위해 프록시를 사용할 필요는 없습니다. Symbol.toPrimitive객체에 대해 같은 방식으로 정의 해도 효과가 있습니다.
Ry-

27

실제로 질문의 첫 부분에 대한 대답은 모든 프로그래밍 언어에서 "예"입니다. 예를 들어, 이것은 C / C ++의 경우입니다 :

#define a   (b++)
int b = 1;
if (a ==1 && a== 2 && a==3) {
    std::cout << "Yes, it's possible!" << std::endl;
} else {
    std::cout << "it's impossible!" << std::endl;
}

27
모든 프로그래밍 언어 에서 가능하다고 생각하지는 않습니다 . 예를 들어, 모든 언어에 전처리 기가있는 것은 아닙니다. 그 문제에 대해 모든 언어 &&가 논리적 "and"에 사용 되는 것은 아닙니다 .
Keith Thompson

3
연산자 오버로드를 사용하는 PythonC ++ 에서 모두 작동하는 방법을 찾았습니다 .
Donald Duck

7
그리고 리플렉션을 사용하고 정수 캐시를 엉망으로 Java로 할 수 있습니다.
CAD97

7
언어로 그것을 할 수없는 것은 그 자리에 woudn't 지원 돌연변이는, 예를 들어 비교 아무것도 하스켈에서 사용할 수 없음
제이슨 카

4
C ++이 아닌 JavaScript에 대한 질문입니다.
모든 노동자는 필수

26

동일하지만 다르지만 여전히 동일합니다 (여러 번 "테스트"될 수 있음).

const a = { valueOf: () => this.n = (this.n || 0) % 3 + 1}
    
if(a == 1 && a == 2 && a == 3) {
  console.log('Hello World!');
}

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

내 생각은 Number 객체 유형 방정식이 작동하는 방식에서 시작되었습니다.


4
두 번째로 작동합니다!
Salman A

25

Symbols를 사용하는 ECMAScript 6 답변 :

const a = {value: 1};
a[Symbol.toPrimitive] = function() { return this.value++ };
console.log((a == 1 && a == 2 && a == 3));

==사용법 으로 인해 JavaScript는 a두 번째 피연산자 ( 1, 2) 3에 가까운 것으로 강제 됩니다 . 그러나 JavaScript가 자체적으로 강제를 파악하기 전에를 호출하려고합니다 Symbol.toPrimitive. Symbol.toPrimitiveJavaScript 를 제공 하면 값이 사용됩니다. 그렇지 않으면 JavaScript는을 호출 valueOf합니다.


24

나는 이것이 그것을 구현하는 최소한의 코드라고 생각합니다.

i=0,a={valueOf:()=>++i}

if (a == 1 && a == 2 && a == 3) {
  console.log('Mind === Blown');
}

각 호출 valueOf에서 전역 변수를 증가시키는 사용자 지정으로 더미 객체를 만듭니다 i. 23 자!


14

이것은 전역 변수를 일으키는 멋진 부작용으로 defineProperty를 사용합니다!

var _a = 1

Object.defineProperty(this, "a", {
  "get": () => {
    return _a++;
  },
  configurable: true
});

console.log(a)
console.log(a)
console.log(a)


8
클로저를 사용할 수 있습니다 a: get: (a => () => ++a)(0),전역 필요 없음.
Nina Scholz

13
@NinaScholz, 그러나 우리는 여기서 나쁜 관행에 대해 이야기하고 있습니다-그냥 알려주세요 : D
Ben Aubin

1

valueOf클래스 선언에서 재정의 하면 다음을 수행 할 수 있습니다.

class Thing {
    constructor() {
        this.value = 1;
    }

    valueOf() {
        return this.value++;
    }
}

const a = new Thing();

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

일어나는 일은 valueOf각 비교 연산자에서 호출됩니다. 첫 번째 a값은 같고 1두 번째 a값은 같을 것입니다. 2매번 valueOf호출 되기 때문에a 증가된다.

따라서 console.log가 실행되고 (어쨌든 터미널에서) Thing: { value: 4}조건부가 true임을 나타냅니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.