Hãy chơi nhiều hơn một chút!
Đầu tiên, chúng ta hãy vui vẻ!:
//----------#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
Ok, chúng ta hãy cố gắng hiểu những hành vi điên rồ này, từng cái một:
1) Ở đây, {}được phân tích cú pháp dưới dạng một khối mã trống. Không có sự gán, phủ định, nhóm (có dấu ngoặc đơn) hoặc bất kỳ cú pháp nào chỉ ra cho trình phân tích cú pháp rằng đây {}là một đối tượng theo nghĩa đen, giả định mặc định là nghĩ rằng nó chỉ đơn giản là một khối trống vô dụng.
Đây là một bằng chứng về hành vi này:
{ alert(123) }[true]
Mã ở trên sẽ hiển thị cảnh báo bình thường và sẽ được đánh giá là [true], theo cách tương tự {}[true].
Khối báo cáo không có dấu chấm phẩy
Một câu lệnh kiểu khối không cần dấu chấm phẩy sau nó.
Ví dụ:
for(var i=0; i < 1; i++){}function a(){};alert("Passed here!");if(true){}alert("Passed here too!")
Cả hai cảnh báo được hiển thị.
Vì vậy, chúng ta có thể thấy rằng một tuyên bố khối trống, không có dấu chấm phẩy, là hợp lệ và đơn giản là không làm gì cả. Theo cách này, khi bạn nhập vào {}[true]Bảng điều khiển Công cụ dành cho nhà phát triển (hoặc Fireorms), giá trị được đánh giá sẽ là giá trị của câu lệnh biểu thức cuối cùng . Trong trường hợp này, câu lệnh biểu thức cuối cùng là[true] .
2) Trong ngữ cảnh gán, trình phân tích cú pháp sẽ đảm bảo rằng đó {}là một đối tượng bằng chữ. Khi bạn thực hiện var a = {}[true], bạn loại bỏ bất kỳ sự mơ hồ nào và loại bỏ trình phân tích cú pháp {}không phải là một câu lệnh chặn.
Vì vậy, ở đây, bạn đang cố gắng để có được một giá trị với một khóa"true" từ một đối tượng trống. Rõ ràng, không có cặp khóa-giá trị với tên khóa này. Bằng cách này, một biến là không xác định.
Các từ dành riêng như các khóa đối tượng
ECMAScript 5 cho phép các khóa đối tượng là các từ dành riêng. Vì vậy, các khóa sau là hợp pháp:
var obj = {if: 111, for: 222, switch: 333, function: 444, true: 555}
3) Giải thích tương tự ví dụ 1 . Nhưng ... Nếu { b: 12345 }phần đó được coi là một câu lệnh chặn thì loại b: 12345câu lệnh đó là gì ??
... (?????)
Đó là một tuyên bố nhãn , bạn đã thấy nó trước đây ... Nó được sử dụng trong các vòng lặp và trong switch. Dưới đây là một vài liên kết thú vị về các tuyên bố nhãn: 1 , (2) [ Cách tốt nhất để thoát khỏi các vòng lặp lồng nhau trong Javascript?, (3) [ Làm thế nào để phá vỡ các vòng lặp lồng nhau trong javascript? .
GHI CHÚ: Chỉ cần cố gắng đánh giá điều này:
{a: 1, b: 2} //=>>>SyntaxError: Unexpected token :
Báo cáo nhãn không thể được phân tách bởi phân tách bằng toán tử dấu phẩy , bạn sẽ cần tách chúng bằng dấu chấm phẩy. Vì vậy, điều này là hợp lệ:{a: 1; b: 2}
4) Xem giải thích cho các ví dụ 1 và 3 ...
5) Một lần nữa, chúng ta { b: 12345 }bị coi là một khối mã và bạn đang cố truy cập vào một thuộc tính của khối mã bằng cách sử dụng ký hiệu dấu chấm , và rõ ràng, điều này không được phép và trình phân tích cú pháp ném một"Unexpected token :" ngoại lệ.
6) Mã gần giống với ví dụ trên, nhưng bằng cách bao quanh { b: 12345 }câu lệnh với toán tử nhóm biểu thức , trình phân tích cú pháp sẽ biết đó là một đối tượng. Bằng cách này, bạn sẽ có thể truy cập vào"b" tài sản bình thường.
7) Hãy nhớ ví dụ 2 , chúng ta có một bài tập ở đây, trình phân tích cú pháp biết rằng{ b: 12345 } là một đối tượng.
8) Giống hệt với ví dụ trên, nhưng thay vì ký hiệu dấu chấm, ở đây chúng tôi đang sử dụng ký hiệu dấu ngoặc .
9) Tôi đã nói rằng "identifier: value"cú pháp này trong một câu lệnh khối là một nhãn. Nhưng, bạn cũng phải biết rằng tên nhãn không thể là từ khóa dành riêng (ngược lại với tên thuộc tính đối tượng). Khi chúng tôi cố gắng xác định một nhãn được gọi "true", chúng tôi đã nhận được một SyntaxError.
10) Một lần nữa, chúng ta đang làm việc với một đối tượng. Không có vấn đề sử dụng các từ dành riêng ở đây. =)
11) Cuối cùng, chúng ta có điều này:!{}[true]
Chúng ta hãy tách những thứ ở đây:
a) Bằng cách phủ nhận, chúng tôi thông báo cho trình phân tích cú pháp rằng đó {}là một đối tượng .
b) Như trong ví dụ 2 , một {}đối tượng không có thuộc tính được gọi true, vì vậy biểu thức này sẽ ước tính undefined.
c) Kết quả cuối cùng là sự phủ định undefinedgiá trị. Javascript thực hiện chuyển đổi loại ẩn và undefinedgiá trị là giả .
d) Vì vậy, sự phủ định falselà ... true!
var o = {}; o[true] === undefined.