etc./StackOverFlow

(a== 1 && a ==2 && a==3) 참으로 평가될 수 있습니까?

청렴결백한 만능 재주꾼 2021. 11. 23. 03:44
반응형

질문자 :Dimpu Aravind Buddha


진행자 참고 사항: 코드를 편집하거나 이 알림을 제거하려는 충동을 억제하십시오. 공백의 패턴은 질문의 일부일 수 있으므로 불필요하게 변조되어서는 안 됩니다. "공백이 중요하지 않음" 진영에 있다면 코드를 있는 그대로 받아들일 수 있어야 합니다.

JavaScript에서 (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 때문에 valueOf가 더 합리적일 것입니다. toString 에서 문자열을 반환했다면 엔진은 문자열을 숫자로 변환하려고 시도했지만 경로는 약간 더 길지만 동일한 최종 결과를 제공합니다.


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 스크립트에서 공백 문자로 해석되지 않는 유니코드 공백 문자인 반각 한글(익숙하지 않은 사람들을 위한 한국어)입니다. 이는 식별자에 유효한 문자임을 의미합니다. 따라서 세 가지 완전히 다른 변수가 있습니다. 하나는 뒤에 한글이 있고, 하나는 앞에 있고, 마지막에는 단지가 있습니다. 가독성을 위해 공백을 _ 로 바꾸면 동일한 코드가 다음과 같이 보일 것입니다.

 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이 아닌 비 조인자 문자도 변수 이름에 허용 된다는 사실에 주목했습니다. 너비가 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!") }


Jeff

것이 가능하다!

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


Jonas Wilms

getter 또는 valueOf가 없는 예:

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

== 가 배열에 대해 .join 을 호출하는 toString 을 호출하기 때문에 작동합니다.

toString/valueOf 해당하는 ES6인 Symbol.toPrimitive 를 사용하는 또 다른 솔루션:

 let i = 0; let a = { [Symbol.toPrimitive]: () => ++i }; console.log(a == 1 && a == 2 && a == 3);


Community Wiki

그것이 가능한지(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; } } }


ocomfd

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

 var a = { r: /\d/g, valueOf: function(){ return this.r.exec(123)[0] } } if (a == 1 && a == 2 && a == 3) { console.log("!") }

Object가 프리미티브(예: Number)와 비교할 때 호출되는 valueOf 메소드로 인해 작동합니다. 주요 트릭은 a.valueOf g 플래그를 사용하여 정규식에서 exec 를 호출하기 때문에 매번 새 값을 반환하므로 일치하는 항목이 발견될 때마다 해당 정규식의 lastIndex 따라서 처음 this.r.lastIndex == 0 , 1lastIndex : this.r.lastIndex == 1 업데이트하므로 다음 번에 정규식은 2 와 일치하게 됩니다.


Kos

예를 들어 SharedArrayBuffer와 일부 기본 스크립트를 통해 2명의 웹 작업자가 a 경우에 가능합니다. 가능성은 낮지만 코드가 기계어로 컴파일될 때 웹 작업자가 a==1 , a==2a==3 이 충족되도록 적시에 a 변수를 업데이트할 가능성이 있습니다.

자바스크립트에서 웹 워커와 SharedArrayBuffer가 제공하는 멀티 쓰레드 환경에서 경쟁 조건의 예가 될 수 있습니다.

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

메인.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)

작업자.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') })

수정자.js

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

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

여기에 이미지 설명 입력

두 번째 시도:

여기에 이미지 설명 입력

내가 말했듯이 가능성은 낮지만 충분한 시간이 주어지면 조건에 맞을 것입니다.

팁: 시스템에서 시간이 너무 오래 걸리는 경우. a == 1 && a == 2 만 시도하고 Math.random()*3Math.random()*2 . 목록에 더 많이 추가하면 적중 기회가 줄어듭니다.


mehulmpt

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

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

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


jontro

이것은 일련의 자체 덮어쓰기 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."); } })();


Patrick Dark

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

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


Nina Scholz

이 답변이 이미 게시되어 있지 않으므로 이 답변도 믹스에 던질 것입니다. 이것은 반각 한글 공백에 대한 Jeff의 답변과 유사합니다.

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

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

a - 라틴 소문자 A
- 전체 너비 라틴어 소문자 A
а - 키릴 소문자 A

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

가장 일반적으로 가짜 도메인 이름(예: wikipediа.org (키릴 자모) 대 wikipedia.org (라틴어))에 동형 문자 공격의 전체 클래스가 있지만 코드에도 나타날 수 있습니다. 일반적으로 언더핸드라고 합니다(코멘트에서 언급했듯이 [underhanded] 질문은 이제 PPCG에서 주제를 벗어났지만 이러한 종류의 항목이 표시되는 일종의 도전 과제였습니다). 이 웹사이트 를 사용하여 이 답변에 사용된 상형 문자를 찾았습니다.


Draco18s no longer trusts SE

예, 가능합니다!

» 자바스크립트

 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, 어떻게?

그래서 나는 당신에게 다음과 같이 말한 사람에게 Yes, 그것은 가능 하다고 말하는 것으로 충분하다고 생각합니다 . 불가능한 것은 없습니다

if 뒤에 숨겨진 문자를 사용하여 if 와 비슷한 함수를 만들었습니다. JavaScript에서는 키워드를 재정의할 수 없으므로 강제로 이 방법을 사용했습니다. 그것은 가짜 if 이지만 이 경우에는 효과가 있습니다!


» C#

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

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

라이브 데모


RAM

자바스크립트

a == a +1

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

그것은 수 있다면 것을 의미 a 충분히 큰이며,이 세 개의 연속 정수로 동일한 것으로 간주 할 수있다 :

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

자바

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

Eric Duminil

이것은 숨겨진 문자(U+115F, U+1160 또는 U+3164)를 사용하여 1 , 23 처럼 보이는 변수를 생성하는 @Jeff의 답변 *의 반전된 버전입니다.

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


Salman A

인터뷰 규칙 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 ){ console.log( 'Oh dear, what have we done?' ); }


MonkeyZeus

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

"글쎄, 나에게 즉각적으로 명확하지 않은 이상한 상황에서는 예일 수 있습니다. 하지만 실제 코드에서 이것을 만난다면 일반적인 디버깅 기술을 사용하여 그것이 하고 있던 일을 하는 방법과 이유를 알아낼 것입니다. 그런 다음 해당 상황을 피하기 위해 코드를 즉시 리팩터링합니다... 하지만 더 중요한 것은, 그것이 복잡한 코드의 바로 정의이기 때문에 처음부터 그 코드를 절대 작성하지 않을 것이며, 나는 절대로 복잡한 코드를 작성하지 않으려고 노력합니다."

일부 면접관은 분명히 매우 까다로운 질문을 하는 것을 불쾌하게 여길 것입니다. 하지만 의견이 있는 개발자는 신경 쓰지 않습니다. 특히 합리적인 생각으로 이를 뒷받침하고 내 질문을 자신에 대한 의미있는 진술.


Frank W. Zammetti

그러한 인터뷰 질문을 받은 적이 있다면(또는 코드에서 똑같이 예기치 않은 동작을 발견한 경우) 언뜻 보기에 불가능해 보이는 동작을 일으킬 수 있는 종류에 대해 생각하십시오.

  1. 인코딩 : 이 경우 보고 있는 변수는 생각하는 변수가 아닙니다. 이것은 변수 이름을 다른 이름처럼 보이게 하기 위해 동형 문자 또는 공백 문자 를 사용하여 의도적으로 유니코드를 어지럽히는 경우에 발생할 수 있습니다. fl 을 유니코드 'LATIN SMALL LIGATURE FL'(U+FB02)로 바꾸는 것과 같은 일부 "자동 서식 지정"을 수행했기 때문에).

  2. 경쟁 조건 : 경쟁 조건 이 발생할 수 있습니다. 즉, 개발자가 예상한 순서대로 코드가 실행되지 않는 상황입니다. 경합 조건은 다중 스레드 코드에서 자주 발생하지만 다중 스레드가 경합 조건에 대한 요구 사항은 아닙니다. 비동기성은 충분합니다(혼동 하지 마십시오. 비동기가 후드 아래에서 다중 스레드가 사용된다는 의미는 아닙니다 ).

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

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

  3. Side-effects : 동등 비교 연산의 부작용(여기의 예에서처럼 명확할 필요는 없으며 종종 부작용이 매우 미묘합니다).

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

물론, 인터뷰 질문과 여기에 있는 샘플은 모두 매우 인위적으로 보입니다. 그러나 그들은 다음을 잘 상기시킵니다.

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

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


Dirk Vollmar

배열을 사용하여 원하는 값을 표시하는 또 다른 변형이 있습니다.

 const a = { n: [3,2,1], toString: function () { return anpop(); } } if(a == 1 && a == 2 && a == 3) { console.log('Yes'); }


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


BaggersIO

프록시 사용:

 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: 0 } . 여기서 i 속성은 카운터입니다.
  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

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


IceCreamYou

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

Gustavo Rodríguez

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

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


Preda7or

기호를 사용하는 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.toPrimitive 를 제공하면 JavaScript는 함수가 반환하는 값을 사용합니다. 그렇지 않은 경우 JavaScript는 valueOf 호출합니다.


Omar Alshaker

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

 i=0,a={valueOf:()=>++i} if (a == 1 && a == 2 && a == 3) { console.log('Mind === Blown'); }

각 호출에서 i 를 증가시키는 valueOf 로 더미 객체를 생성합니다. 23명의 캐릭터!


gafi

이것은 전역 변수를 유발하는 멋진 부작용과 함께 defineProperty를 사용합니다!

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


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 처음에, a 동일 할 것이다 1 번째에, a 동일 할 것이다 2 , 및 기타 등등마다 때문에 valueOf 호출의 값 a 증가된다.

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


Jonathan Kuhl

느슨한 동등 연산자(==) 의 비밀은 두 값을 공통 유형으로 변환하려고 시도한다는 것을 이미 알고 있습니다. 결과적으로 일부 기능이 호출됩니다.

ToPrimitive(A) A.toStringA.valueOf 메서드의 다양한 시퀀스를 호출하여 개체 인수를 기본 값으로 변환하려고 시도합니다.

Symbol.toPrimitive , .toString , .valueOf 정수를 사용하는 다른 답변과 같이. 이와 같이 Array.pop 이 있는 배열을 사용하는 솔루션을 제안합니다.

 let a = { array: [3, 2, 1], toString: () => a.array.pop() }; if(a == 1 && a == 2 && a == 3) { console.log('Hello World!'); }

이런 식으로 우리는 다음과 같은 텍스트로 작업할 수 있습니다.

 let a = { array: ["World", "Hello"], toString: () => a.array.pop() }; if(a == "Hello" && a == "World") { console.log('Hello World!'); }


Nguyễn Văn Phong

출처 : http:www.stackoverflow.com/questions/48270127/can-a-1-a-2-a-3-ever-evaluate-to-true

반응형