it-swarm-ko.tech

Can (a == 1 && a == 2 && a == 3)는 true로 평가됩니까?

진행자 주 : 코드를 편집하거나이 통지를 삭제할 것을 강력히 권고하십시오. 공백의 패턴은 질문의 일부일 수 있으므로 불필요하게 변경해서는 안됩니다. "공백이 중요하지 않음"상태에있는 경우 코드를 그대로 수락 할 수 있어야합니다.

(a== 1 && a ==2 && a==3)가 JavaScript에서 true으로 평가 될 수 있습니까?

이것은 주요 기술 회사가 묻는 인터뷰 질문입니다. 2 주 전 돌아 왔지만 아직 답을 찾으려고합니다. 나는 우리가 일상 업무에서 그런 코드를 쓰지 않는다는 것을 알고 있지만, 나는 호기심이 많다.

2376

== works )를 활용하면 사용자 정의 toString (또는 valueOf) 함수를 사용하여 객체를 만들면 사용할 때마다 반환되는 내용이 3 가지 조건을 모두 충족하도록 변경됩니다.

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

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


이 작동하는 이유는 느슨한 항등 연산자를 사용하기 때문입니다. loose equality를 사용할 때 피연산자 중 하나가 다른 피연산자와 다른 유형이면 엔진은 다른 피연산자로 변환하려고 시도합니다. 왼쪽에있는 객체의 경우와 오른쪽에있는 숫자의 경우, 호출 가능한 경우 valueOf을 먼저 호출하여 객체를 숫자로 변환하려고 시도하고 실패하면 toString을 호출합니다. 이 경우 toString을 사용했습니다. 왜냐하면 valueOf이 더 적합 할 것이기 때문입니다. 대신에 toString에서 문자열을 반환했다면, 엔진은 그 문자열을 약간 더 긴 경로를 사용하더라도 동일한 최종 결과를주는 숫자로 변환하려고 시도했을 것입니다.

3185
Kevin B

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

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

이러지 마 진심으로.

편집 : 변수를 시작할 수는 없지만 제로 너비 소목 장이제로 너비 비 조이너 문자도 변수에 허용됩니다. 이름- 폭이 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!")
}
2025
Jeff

IT IS 가능합니다!

var i = 0;

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

with을 세 가지 다른 값으로 평가하려면 a 문 내부에 getter를 사용합니다.

... 이것은 여전히 ​​이것이 실제 코드에서 사용되어야한다는 것을 의미하지는 않습니다 ...

더 나쁜 것은,이 트릭은 ===의 사용에도 적용됩니다.

  var i = 0;

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

591
Jonas Wilms

Getter 또는 valueOf가없는 예제 :

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

이것은 ==.join를 호출하는 toString을 호출하기 때문에 효과적입니다.

Symbol.toPrimitive와 동일한 ES6 인 toString/valueOf를 사용하는 또 다른 해결 방법은 다음과 같습니다. 

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

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

458
georg

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

259
mmmaaa

정규식 없이는 아무 것도 할 수 없을 때 :

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

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

이것은 Object가 프리미티브 (Number와 같은)와 비교 될 때 호출되는 custom valueOf 메소드로 인해 작동합니다. 주요 트릭은 exec 플래그가있는 정규 표현식에서 g을 호출하기 때문에 a.valueOf가 매번 새로운 값을 반환한다는 것입니다.이 플래그는 일치하는 항목이 발견 될 때마다 정규 표현식의 lastIndex 을 업데이트합니다. 그래서 처음 this.r.lastIndex == 01와 일치하고 lastIndex : this.r.lastIndex == 1를 업데이트하므로 다음에 정규 표현식은 2와 일치합니다.

203
Kos

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

186
jontro

이것은 변수 a이 SharedArrayBuffer를 통해 2 명의 웹 작업자와 몇 가지 기본 스크립트를 통해 액세스되는 경우 가능합니다. 가능성은 낮지 만, 코드가 기계 코드로 컴파일 될 때 웹 작업자는 변수 a을 바로 업데이트하여 a==1, a==2a==3 조건을 만족할 수 있습니다.

자바 스크립트에서 웹 작업자와 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 억 회의 반복이 발생합니다.

 enter image description here

두 번째 시도 :

 enter image description here

내가 말했듯이, 기회는 낮을 것이지만, 충분한 시간이 주어진다면, 그것은 조건에 부딪 칠 것이다.

팁 : 시스템에 너무 오래 걸리는 경우. a == 1 && a == 2 만 시도하고 Math.random()*3Math.random()*2으로 변경하십시오. 점점 더 목록에 추가하면 타격의 기회가 떨어집니다.

182
mehulmpt

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

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

145
Patrick Dark

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

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

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

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

이에 대한 일반적인 용어는 "상형 문자"입니다. 같은 모양의 다른 유니 코드 문자입니다. 완전히 구별하기 어려운 일반적으로 three 를 얻기는 어렵지만 경우에 따라 운이 좋을 수도 있습니다. A, A, А 및 Ꭺ는 각각 더 잘 작동합니다 (라틴 -A, 그리스 알파 , 키릴 -ACherokee-A ; 불행히도 그리스어와 체로키 소문자는 라틴어 a : α, 와 너무 다르므로 위의 스 니펫에는 도움이되지 않습니다).

대부분의 가짜 도메인 이름 (예 : wikipediа.org (키릴 자모) 대 wikipedia.org (라틴))에서 동종 문자 공격의 전체 클래스가 있지만 코드에도 표시 될 수 있습니다. [underhanded] 질문에서 PPCG 에 대한 주제를 벗어난 주제가되었지만 여기서는 일종의 도전이되었습니다. 이런 종류의 것들이 나타납니다). 이 답변에 사용 된 상형 문자를 찾기 위해 이 웹 사이트 를 사용했습니다.

129
Draco18s

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

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!');
}

123
Nina Scholz

예, 가능합니다! ????

"자바 스크립트

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

라이브 데모

101
RAM

자바 스크립트

a == a +1

JavaScript에서는 배정 밀도 부동 소수점 숫자로 구현되는 정수 는 있지만 Number 만 있습니다.

즉, Number a이 충분히 큰 경우 3 개의 연속 정수로 간주 될 수 있습니다.

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

사실, 면접관이 요청한 내용 (a=0에서는 작동하지 않음)과 정확히 같지 않지만 숨겨진 기능이나 연산자 오버로딩과 관련된 트릭은 포함되지 않습니다.

다른 언어들

참고로 Ruby와 Python에는 a==1 && a==2 && a==3 솔루션이 있습니다. 약간의 수정으로 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 cache 를 수정할 수 있습니다.

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

이것은 숨겨진 문자 (U + 115F, U + 1160 또는 U + 3164)가 1, 23와 같은 변수를 만드는 데 사용되는 @ Jeff 's answer *의 거꾸로 된 버전입니다.

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

* 그 해답은 제로 너비 비 접합자 (U + 200C)와 제로 너비 결합 자 (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).

78
Salman A

면접의 규칙 번호 하나; 불가능하다고 말하지 마십시오.

숨겨진 성격의 속임수가 필요 없습니다.

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?' );
}

72
MonkeyZeus

솔직히 말해서, 그것이 진실인지 아닌지를 평가할 수있는 방법이 있든 없든 (그리고 다른 사람들이 보여 주듯이 여러 가지 방법이 있습니다), 제가 찾고자하는 대답은 수백 가지의 인터뷰를 수행 한 사람으로 말하면됩니다. 의 라인을 따라 뭔가 :

"글쎄, 나에게 즉시 명백하지 않은 이상한 환경 하에서는 그렇다. 그렇지만 실제 코드에서이 문제가 발생하면, 일반적인 디버깅 기술을 사용하여 어떻게 그리고 왜하고 있는지를 파악할 수있을 것이다. 그 상황을 피하기 위해 즉시 코드를 리팩터링합니다.하지만 더 중요한 것은 : 코드가 복잡한 코드의 바로 정의이기 때문에 절대적으로 코드를 작성하지 않을 것이고, 복잡한 코드를 쓰지 않으려 고 노력한다는 것입니다. ".

일부 인터뷰하는 사람들은 분명히 매우 까다로운 질문이 나오게하는 것에 대해 불쾌감을 느낍니다.하지만 의견을 가진 개발자는 생각할 필요가 없습니다. 특히 합리적인 생각으로이를 뒷받침 할 수 있고 내 질문에 답할 수있을 때 좋습니다. 그들 자신에 대한 의미있는 진술.

66
Frank W. Zammetti

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

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

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

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

    웹 작업자가있는 JavaScript는 여러 스레드를 가질 수 있으므로 약간 다릅니다. @mehulmpt는 우리에게 위대한 웹 워커를 사용한 개념 증명 을 보여주었습니다.

  3. 부작용 : 부작용 : 평등 비교 연산의 부작용 (여기서 예 에서처럼 명확하지 않아도 됨) 효과는 매우 미묘합니다).

이러한 종류의 문제는 JavaScript뿐만 아니라 많은 프로그래밍 언어로 나타날 수 있으므로 고전적인 JavaScript WTFs1.

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

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

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

42
Dirk Vollmar

배열을 사용하여 원하는 모든 값을 나타낼 수있는 또 다른 변형입니다.

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

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

41
Théophile

좋아, 발전기를 이용한 또 다른 해킹 :

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!');
}

31
BaggersIO

실제로 질문의 첫 번째 부분에 대한 대답은 모든 프로그래밍 언어에서 "예"입니다. 예를 들어, 이것은 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
Gustavo Rodríguez

프록시 사용 :

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 속성"작업)에 대한 작업을 가로 채기 때문에 기본 객체 비헤이비어 이외의 작업을 수행 할 수 있습니다. 이 경우 ==가 각 숫자와 비교하기 위해 유형을 강제 할 때 a에서 "속성 가져 오기"액션이 호출됩니다. 이것은 일어난다 :

  1. i 속성이 우리 카운터 인 { i: 0 }라는 대상 객체를 만듭니다.
  2. 우리는 대상 객체에 대한 프록시를 생성하고이를 a에 할당합니다
  3. a == 비교에 대해 a 유형이 원시 값으로 강제 변환됩니다.
  4. 이 형식 변환은 내부적으로 a[Symbol.toPrimitive]()을 호출하게됩니다.
  5. Proxy는 "get handler"를 사용하여 a[Symbol.toPrimitive] 함수를 가져 오는 것을 가로막습니다.
  6. 프록시의 "get 처리기"는 가져온 속성이 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

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

27
IceCreamYou

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

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 객체 유형 방정식이 작동하는 방식부터 시작되었습니다.

26
Preda7or

Symbols를 사용하는 ECMAScript 6 답변 :

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

== 사용으로 인해 자바 스크립트는 a을 두 번째 피연산자 (여기서는 1, 2, 3)에 가까운 것으로 강제 변환합니다. 그러나 JavaScript가 자체적으로 강제 변환을 시도하기 전에 Symbol.toPrimitive 를 호출하려고 시도합니다. Symbol.toPrimitive를 제공하면 JavaScript는 함수가 반환하는 값을 사용합니다. 그렇지 않으면 JavaScript는 valueOf 을 호출합니다.

23
Omar Alshaker

이 구현하는 최소한의 코드를 생각합니다.

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

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

각 호출마다 전역 변수 valueOf을 증가시키는 사용자 정의 i을 사용하여 더미 객체를 만듭니다. 23 자!

23
Gaafar

이것은 하나의 defineProperty와 Nice 변수를 사용하여 전역 변수를 발생시킵니다!

var _a = 1

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

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

11
Ben Aubin

클래스 선언에서 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이 호출된다는 것입니다. 첫 번째 경우 a1와 같고, 두 번째 a2와 같고 계속 반복됩니다. valueOf이 호출 될 때마다 a 값이 증가하기 때문입니다.

따라서 console.log는 조건부임을 나타내는 Thing: { value: 4}를 발생시키고 출력합니다 (어쨌든).

0
Jonathan Kuhl