javascript - what - 자바스크립트 스프레드 연산자




++[[]][+[]]+[+[]]가 문자열 "10"을 반환하는 이유는 무엇입니까? (6)

  1. 단항 + 주어진 문자열이 숫자로 변환됩니다.
  2. 문자열을 변환하고 1 씩 증가시키는 연산자 증가
  3. [] == ''. 빈 문자열
  4. + ''또는 + []는 0을 평가합니다.

    ++[[]][+[]]+[+[]] = 10 
    ++[''][0] + [0] : First part is gives zeroth element of the array which is empty string 
    1+0 
    10
    

이것은 유효하며 JavaScript에서 문자열 "10" 을 반환합니다 ( 여기에 더 많은 예제가 있음 ).

console.log(++[[]][+[]]+[+[]])

왜? 여기서 무슨 일이 일어나고있는거야?


+ []는 0으로 평가되고 [...] 그 다음 합계 (+ 연산)는 배열 내용을 쉼표로 결합 된 요소로 구성된 문자열 표현으로 변환합니다.

배열의 인덱스를 취하는 것과 같은 다른 것 (+ 연산보다 우선 순위가 높습니다)은 서수이며 재미 있지 않습니다.


다음은이 질문에 답하는 블로그 게시물 에서 수정 한 것입니다.이 질문은 아직 닫았지만 게시했습니다. 링크는 ECMAScript 3 사양의 HTML 사본으로, 오늘날 일반적으로 사용되는 웹 브라우저의 JavaScript 기준선입니다.

첫째, 주석 : 이러한 종류의 표현은 어떤 (정상적인) 제작 환경에서도 결코 나타나지 않을 것이며 독자가 자바 스크립트의 더러운 부분을 얼마나 잘 알고 있는지 연습하는 용도로만 사용됩니다. JavaScript 연산자가 유형간에 암묵적으로 변환한다는 일반적인 원칙은 일반적인 변환과 마찬가지로 유용하지만이 경우의 세부 사항 대부분은 유용하지 않습니다.

++[[]][+[]]+[+[]] 표현식은 처음에 다소 부각되고 어둡게 보일 수 있지만 실제로는 상대적으로 쉽게 분리 된 표현식으로 분해됩니다. 아래에서는 간단히 괄호를 추가했습니다. 나는 당신이 아무 것도 변경하지 않는다는 것을 확신 할 수있다, 그러나 당신이 그 때 그것을 분류하고 싶은 경우에 그룹화 통신 수에 관하여 읽는 것을 자유롭게 느끼십시오. 따라서 표현은 다음과 같이 더 명확하게 표현 될 수 있습니다.

( ++[[]][+[]] ) + ( [+[]] )

이 점을 깨고 +[]0 평가 됨으로써 단순화 할 수 있습니다. 왜 이것이 사실인지 스스로를 만족 시키려면 unary + 연산자를 확인하고 ToPrimitive 로 끝나는 약간의 흔적을 따라 빈 배열을 빈 문자열로 변환 한 다음 ToNumber 의해 마지막으로 0 으로 변환합니다. 이제 +[] 의 각 인스턴스를 0 으로 대체 할 수 있습니다.

( ++[[]][0] ) + [0]

이미 간단합니다. ++[[]][0] 에 대해서는 bclary.com/2004/11/07/#a-11.4.4 ( ++ ), 빈 배열 ( [[]] 단일 요소가있는 배열을 정의하는 배열 리터럴속성 접근 자 ( [0] )는 배열 리터럴로 정의 된 배열에서 호출됩니다.

그래서 [[]][0][[]][0] 단순화 할 수 있고 ++[] , 맞습니까? 실제로 ++[] 평가할 때 오류가 발생하기 때문에 처음에는 혼란 스러울 수 있습니다. 그러나 ++ 의 성격에 대해 조금 생각하면 변수 (예 : ++i ) 또는 객체 속성 (예 : ++obj.count )을 증가시키는 데 사용됩니다. 가치 평가뿐만 아니라 그 가치를 어딘가에 저장합니다. ++[] 의 경우 업데이트 할 객체 속성이나 변수에 대한 참조가 없기 때문에 새로운 값을 넣을 곳이 없습니다. 스펙 측면에서 이것은 접두사 증가 연산자에 의해 호출되는 내부 PutValue 연산에 의해 다뤄집니다.

그럼, ++[[]][0] 는 무엇을합니까? 음, +[] 와 비슷한 논리에 의해, 내부 배열은 0 으로 변환되고이 값은 1 로 증가되어 최종 값 1 을 얻습니다. 외부 배열의 특성 0 값은 1 로 갱신되고 전체 표현식은 1 평가됩니다.

이로 인해 우리는

1 + [0]

... 더하기 연산자 의 간단한 사용법입니다. 양 피연산자가 먼저 ToPrimitive 값 중 하나가 문자열이면 문자열 연결이 수행되고 그렇지 않으면 숫자 추가가 수행됩니다. [0]"0" 변환되므로 문자열 연결이 사용되어 "10" 생성합니다.

마지막으로, 즉시 명백하지 않을 수도있는 것은 Array.prototypetoString() 또는 valueOf() 메서드 중 하나를 재정의하면 표현식의 결과가 변경된다는 것입니다. 개체를 원시 값으로 변환합니다. 예를 들어 다음과 같습니다.

Array.prototype.toString = function() {
  return "foo";
};
++[[]][+[]]+[+[]]

... "NaNfoo" 생성합니다. 왜 이런 일이 일어나는지는 독자의 연습 문제로 남아 있습니다 ...


아마도 숫자없이 "10"으로 표현식을 평가할 수있는 가장 짧은 방법은 다음과 같습니다.

+!+[] + [+[]] // "10"

-~[] + [+[]] // "10"

// ========== 설명 ========== \\

+!+[] : +[] !0 변환 !0true 로 변환됩니다. +true 는 1로 변환됩니다. -~[] = -(-1) 1

[+[]] : +[] 0으로 변환합니다. [0] 은 단일 요소가 0 인 배열입니다.

그런 다음 JS는 1 + [0] , 즉 Number + Array 표현식을 평가합니다. 그런 다음 ECMA 사양이 작동합니다. + 연산자는 기본 Object 프로토 타입에서 toString()/valueOf() 함수를 호출하여 두 피연산자를 모두 문자열로 변환합니다. 표현식의 두 피연산자가 모두 숫자 일 경우 추가 기능으로 작동합니다. 트릭은 배열이 요소를 연결된 문자열 표현으로 쉽게 변환한다는 것입니다.

몇 가지 예 :

1 + {} //    "1[object Object]"
1 + [] //    "1"
1 + new Date() //    "1Wed Jun 19 2013 12:13:25 GMT+0400 (Caucasus Standard Time)"

두 개의 Objects 추가 결과가 NaN 멋진 예외가 있습니다.

[] + []   //    ""
[1] + [2] //    "12"
{} + {}   //    NaN
{a:1} + {b:2}     //    NaN
[1, {}] + [2, {}] //    "1,[object Object]2,[object Object]"

이 것은 동일하지만 조금 더 작게 평가됩니다.

+!![]+''+(+[])
  • [] - 배열을 변환하거나 변환 할 때 0으로 변환되므로 + [] = 0이됩니다.
  • ! [] - false로 평가되므로 !! []가 true로 평가됩니다.
  • + !! [] - true를 true로 평가하는 숫자 값으로 변환합니다.이 경우 1입니다.
  • + ''- 빈 문자열을 표현식에 추가하여 숫자가 문자열로 변환되도록합니다.
  • + [] - 0으로 계산됩니다.

그렇게 평가된다.

+(true) + '' + (0)
1 + '' + 0
"10"

이제 얻었습니다. 다음을 시도하십시오.

_=$=+[],++_+''+$

++[[]][+[]] => 1 // [+[]] = [0], ++0 = 1
[+[]] => [0]

그런 다음 문자열 연결이 있습니다.

1+[0].toString() = 10




syntax