Давайте пограємо ще трохи!
Спочатку давайте повеселитися !:
//----------#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) [ Як розбити вкладені петлі в JavaScript? .
ПРИМІТКА. Просто спробуйте оцінити це:
{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]
Давайте розділимо тут речі:
а) Роблячи заперечення, ми інформуючи аналізатор , що {}є об'єктом .
b) Як показано в прикладі 2 , {}об'єкт не має властивості, яку називають true, тому цей вираз буде оцінено до undefined.
в) Кінцевим результатом є заперечення undefinedвартості. Javascript виконує перетворення типу імпліцитності , а undefinedзначення - хибне .
г) Отже, заперечення - falseце ... true!
var o = {}; o[true] === undefined.