조금 더 놀자!
먼저 재미있게 놀자! :
//----------#01#-----------
{}[true]; //[true]
//----------#02#-----------
var a = {}[true];
console.log(a); //undefined
//----------#03#-----------
{ b: 12345 }[true]; //[true]
//----------#04#-----------
{ b: 12345 }["b"]; //evaluates to ["b"] ?!?
//----------#05#-----------
{ b: 12345 }.b; // "Unexpected token ."
//----------#06#-----------
({ b: 12345 }).b; //12345
//----------#07#-----------
var c = { b: 12345 }.b;
console.log(c); //12345
//----------#08#-----------
var c = { b: 12345 }["b"];
console.log(c); //12345
//----------#09#-----------
{ true: 54321 }[true]; // "SyntaxError: Unexpected token : "
//----------#10#-----------
var d = { true: 54321 }[true]; //No error here ¬¬
console.log(d); //54321
//----------#11#-----------
!{}[true]; // true
자,이 미친 행동을 하나씩 이해해 봅시다 :
1) 여기서는 {}빈 코드 블록으로 구문 분석됩니다. 할당, 부정, 그룹화 (괄호 포함) 또는 구문 분석기에 이것이 {}객체 리터럴 임을 나타내는 구문이 없으면 기본 가정은 단순히 쓸모없는 빈 블록이라고 생각하는 것입니다.
이것은이 동작의 증거입니다.
{ alert(123) }[true]
위의 코드는 경고를 정상적으로 표시 [true]하며 같은 방식 으로로 평가됩니다 {}[true].
세미콜론이없는 블록 문장
블록 타입 문장은 그 뒤에 세미콜론이 필요하지 않습니다.
예를 들어 :
for(var i=0; i < 1; i++){}function a(){};alert("Passed here!");if(true){}alert("Passed here too!")
두 가지 경고가 모두 표시됩니다.
따라서 세미콜론이없는 빈 블록 명령문은 유효하며 아무 것도 수행하지 않습니다. 이렇게 {}[true]하면 개발자 도구 (또는 Firebug) 콘솔에 입력 할 때 평가 된 값이 마지막 표현식 명령문 의 값이 됩니다. 이 경우 마지막 표현식은 [true]입니다.
2) 할당 컨텍스트에서 파서는 {}객체 리터럴 인지 확인합니다 . var a =을 수행하면 {}[true]모호성을 제거 {}하고 블록 문이 아닌 파서를 끝냅니다 .
그래서 여기서는 "true"빈 객체에서 키로 값을 얻으려고 합니다. 분명히이 키 이름과 키-값 쌍이 없습니다. 이런 식으로 변수는 정의되지 않습니다.
예약 된 단어를 객체 키로
ECMAScript 5를 사용하면 객체 키를 예약어로 사용할 수 있습니다. 따라서 다음 키가 합법적입니다.
var obj = {if: 111, for: 222, switch: 333, function: 444, true: 555}
3) 예제 1 과 동일한 설명 . 그러나 ... { b: 12345 }부품이 블록 문으로 취급되면 b: 12345문 유형은 무엇 입니까 ??
... (?????)
그것은 레이블 문장입니다 , 당신은 이미 전에 보았습니다 ... 그것은 루프와에서 사용됩니다 switch. 레이블 문장에 대한 몇 가지 흥미로운 링크는 다음과 같습니다. 1 , (2) [ Javascript의 중첩 루프에서 벗어날 수있는 가장 좋은 방법은 무엇입니까? , (3) [ 자바 스크립트에서 중첩 루프를 끊는 방법? .
참고 : 이것을 평가하십시오.
{a: 1, b: 2} //=>>>SyntaxError: Unexpected token :
레이블 문은 쉼표 연산자로 구분할 수 없으므로 세미콜론으로 구분해야합니다. 그래서 이것은 유효합니다 :{a: 1; b: 2}
4) 예제 1 과 3에 대한 설명을 참조하십시오 ...
5) 한 번 더, 우리는 { b: 12345 }코드 블록으로 취급되고 있으며 점 표기법 을 사용하여 코드 블록의 속성에 액세스하려고하는데 , 이것이 허용되지 않으며 파서는 "Unexpected token :"예외를 던집니다 .
6) 코드는 위의 예제와 거의 동일하지만 { b: 12345 }구문을 표현식 그룹화 연산자 로 둘러싸면 구문 분석기는 이것이 객체임을 알게됩니다. 이런 식으로, 당신은 "b"일반적으로 속성 에 액세스 할 수 있습니다 .
7) 예제 2를 기억하십시오. 여기서 할당이 있고 파서는 그것이 { b: 12345 }객체 라는 것을 알고 있습니다.
8) 위 예제와 동일하지만 점 표기법 대신 대괄호 표기법을 사용합니다 .
9)"identifier: value" 블록 구문 내 에서이 구문은 레이블 이라고 이미 말했습니다 . 그러나 레이블 이름은 예약 된 키워드 (객체 속성 이름과 반대)가 될 수 없다는 것도 알아야합니다. 우리라는 라벨을 정의했을 때 "true", 우리는있어 SyntaxError.
10) 다시, 우리는 객체를 다루고 있습니다. 예약어를 사용하는 데 아무런 문제가 없습니다. =)
11) 마지막으로, 우리는 이것을 가지고 있습니다 :!{}[true]
여기서 물건을 분리합시다.
a)는 부정함으로써, 우리는이 것을 파서에 알리는 것 {}입니다 오브젝트 .
예에 도시 된 바와 같이, b) 2 하는 {}객체라는 속성이없는 true이런 식으로 계산한다 그래서 undefined.
c) 최종 결과는 undefined가치 의 부정이다 . Javascript는 암시 적 유형 변환을 수행 하며 undefined값이 잘못되었습니다 .
d) 따라서 부정 false은 ... true!
var o = {}; o[true] === undefined.