(! [] + []) [+ []]… 작동 이유 설명


107
alert((![]+[])[+[]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]);

이 코드의 출력은 다음과 같습니다 fail.. 왜?

그건 그렇고, (![]+[])[+!+[]] == 'false'[1]맞죠?. 하지만 왜 ![]+[] == "false"그리고 왜 +!+[] == 1?


14
@Snoob 나는 당신을 신뢰하지 않습니다. 결국 그것은 포크 폭탄입니다.
Johannes Schaub-litb

3
그것은 물론 문자열 리터럴입니다)
이순신 지앙

3
(![]+[])[+[]]"F"( "거짓"의 첫 문자가)이다 (![]+[])[+!+[]]되어 "A"등
마우 페르

3
@Snoob : 말했듯이 브라우저에서 각 표현식을 테스트 할 수 있습니다. alert(![]+[])그럼 시도해 alert(+!+[])보시면 알게 될 것입니다.
Mauricio Scheffer

12
쓸모 없든 아니든, 나는 그것이 흥미로운 질문이라고 생각하고 잘 표현 된 설명을보고 싶습니다. 유용성이나 실용성을 고려하면 많은 코드 골프가 폐쇄됩니다. 연습과 게임은 그 자체로 마음과 사고 과정을 확장하는 데 유용합니다.
John K

답변:


127

@Mauricio가 언급했듯이 (![]+[])[+[]]"f"( "false"의 첫 번째 문자), (![]+[])[+!+[]])"a"등입니다.

어떻게 작동합니까?

첫 번째 문자 'f'를 살펴 보겠습니다.

(![]+[])[+[]]; // 'f'

표현식의 첫 번째 부분 (괄호 사이 ) 은로 구성되며 ![]+[], 더하기 연산자의 첫 번째 피연산자는 ![]이며 이는 false다른 Object 인스턴스와 마찬가지로 배열 객체가 진실 이고 논리 (!) NOT 단항을 적용하기 때문입니다. false예를 들어 값을 생성합니다 .

![]; // false, it was truthy
!{}; // false, it was truthy
!0;  // true, it was falsey
!NaN;  // true, it was falsey

그 다음에는 빈 배열의 두 번째 피연산자 인 빈 배열이 있습니다. 빈 배열의 문자열 표현이 빈 문자열이기 때문에 값을 문자열 []로 변환하기 위해 만들어집니다 false.

false+[]; // "false"
false+''; // "false"

마지막 부분 인 괄호 뒤의 대괄호 쌍은 속성 접근 자이며 빈 배열에 다시 적용된 단항 더하기 연산자로 구성된 식을받습니다.

단항 더하기 연산자가하는 일은 다음과 같은 형식 변환입니다 Number.

typeof +"20"; // "number"

한 번 더, 이것은 빈 배열에 적용되며, 앞서 말했듯이 배열의 문자열 표현은 빈 문자열이며 빈 문자열을 숫자로 변환하면 0으로 변환됩니다.

+[]; // 0, because
+[].toString(); // 0, because
+""; // 0

따라서 몇 단계에서 표현식을 "디코딩"할 수 있습니다.

(![]+[])[+[]];
(false+[])[+[]];
(false+'')[+[]];
(false+'')[0];
('false')[0];  // "f"

문자열 값에 대괄호 표기법을 사용하여 문자에 액세스하는 것은 ECMAScript 3rd의 일부가 아닙니다. 에디션 사양 (이것이 charAt방법이 존재하는 이유입니다 ).

그러나 문자열의 문자를 나타내는 이러한 종류의 "인덱스 속성"은 ECMAScript 5에서 표준화되었으며 표준화 이전에도 많은 브라우저에서이 기능을 사용할 수있었습니다 (IE8 (표준 모드)에서도 가능).


46
이것이 인터뷰 질문이 아니기를 바랍니다.
Inisheer

4
@JTA : 나는 그것을 희망 입니다 ! 나는 통과했을 것입니다 :-D
Mauricio Scheffer

18
"i"는 어디에서 왔습니까?
Josh Stodola

5
@rlemon, int언어에 데이터 유형 이 없습니다 . 사실 모든 숫자는 배정 밀도 64 비트 형식 (IEEE 754 값)입니다. 일부 연산자는 내부적으로 정수 값 (비트 연산자와 같은)으로 작업하더라도 결과는 항상 double입니다. . 은 'i'에서이 예에서 온다 undefined, 그러나 그것은에서 올 수 Infinity예 : (+!+[]/+[+[]]+[])[!+[]+!+[]+!+[]]=> (1/0+'')[3]=> (Infinity+'')[3]=>'i'
CMS

5
@JoshStodola 글쎄, ~ 3 개월 후, 추가 설명. 이 경우 "i"는 "정의되지 않음"에서 나왔지만 여기에 또 다른 트릭이 있습니다. 이 코드는 "false"를 "undefined"로 연결 "falseundefined"하여 [![]]+[][[]]"i"의 인덱스가 10 인 형식 (을 사용하여 생성됨) +!+[]+[+[]]"10"만듭니다. 이것은 "i"를 추출하는 데 사용됩니다 (문자열 인덱스는 분명히 정수로 강제 변환 될 수있는 경우 자바 스크립트에서 사용할 수 있습니다). 그것을 생성하는 최종 구조는 다음과 같습니다.([![]]+[][[]])[+!+[]+[+[]]]
엔트로피
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.