(! [] + []) [+ []]… Giải thích tại sao điều này hoạt động


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

Đầu ra của mã này là: fail. Tại sao?

Nhân tiện (![]+[])[+!+[]] == 'false'[1], phải không ?. Nhưng tại sao ![]+[] == "false"và tại sao +!+[] == 1?


14
@Snoob Tôi không tin bạn. Cuối cùng, đó là một quả bom ngã ba.
Johannes Schaub - litb

3
Đó là một literal chuỗi, of course;)
Yi Jiang

3
(![]+[])[+[]]là "f" (ký tự đầu tiên từ "false"), (![]+[])[+!+[]]là "a", v.v.
Mauricio Scheffer

3
@Snoob: như bạn đã nói, bạn có thể kiểm tra từng biểu thức trên trình duyệt của mình. Hãy thử alert(![]+[])sau đó alert(+!+[])và bạn sẽ thấy.
Mauricio Scheffer

12
Vô ích hay không, tôi thấy đó là một câu hỏi thú vị và muốn xem một lời giải thích cặn kẽ. Nhiều Code Golf sẽ bị đóng cửa nếu tính đến tính hữu ích hoặc tính thực tế. Các bài tập thể dục và trò chơi rất hữu ích để mở rộng tâm trí và quá trình tư duy.
John K

Câu trả lời:


127

Như @Mauricio đã nhận xét (![]+[])[+[]]là "f" (ký tự đầu tiên của "false"), (![]+[])[+!+[]])là "a", v.v.

Làm thế nào nó hoạt động?

Hãy kiểm tra ký tự đầu tiên, 'f':

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

Phần đầu tiên của biểu thức — giữa các dấu ngoặc — được tạo bởi ![]+[], toán hạng đầu tiên của toán tử Phép cộng![]và nó sẽ tạo ra false, bởi vì một đối tượng mảng — như bất kỳ cá thể Đối tượng nào khác — là trung thực và áp dụng Logical (!) NOT một bậc chẳng hạn, nó tạo ra giá trị false.

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

Sau đó, chúng ta có toán hạng thứ hai của phép cộng, một Mảng trống [], điều này được thực hiện chỉ để chuyển đổi falsegiá trị thành Chuỗi, vì biểu diễn chuỗi của một mảng trống chỉ là một chuỗi trống, tương đương với:

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

Phần cuối cùng, cặp dấu ngoặc vuông sau dấu ngoặc, chúng là công cụ truy cập thuộc tính và chúng nhận được một biểu thức, được hình thành bởi Toán tử Unary Plus được áp dụng lại cho một mảng trống.

Những gì Toán tử Unary Plus làm là chuyển đổi kiểu Number, ví dụ:

typeof +"20"; // "number"

Một lần nữa, điều này được áp dụng cho một Mảng trống và như tôi đã nói trước đây, biểu diễn Chuỗi của Mảng là một chuỗi rỗng và khi bạn chuyển đổi một chuỗi rỗng thành Số, nó sẽ được chuyển đổi thành 0:

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

Do đó, chúng ta có thể "giải mã" biểu thức thành một số bước:

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

Lưu ý rằng việc truy cập các ký tự bằng cách sử dụng ký hiệu dấu ngoặc trên các giá trị Chuỗi không phải là một phần của ECMAScript 3. Đặc tả Phiên bản, (đó là lý do tại sao charAtphương pháp này tồn tại).

Tuy nhiên, loại "thuộc tính chỉ mục" đại diện cho các ký tự của một chuỗi đã được tiêu chuẩn hóa trên ECMAScript 5 và thậm chí trước khi tiêu chuẩn hóa, tính năng này đã có sẵn trong một số trình duyệt (ngay cả trong IE8 (chế độ tiêu chuẩn)).


46
Chỉ hy vọng đây không bao giờ là một câu hỏi phỏng vấn.
Inisheer

4
@JTA: Tôi hy vọng là như vậy! Tôi sẽ trôi qua :-D
Mauricio Scheffer

18
Chữ "i" đến từ đâu?
Josh Stodola

5
@rlemon, không có intkiểu dữ liệu trên ngôn ngữ, trên thực tế, tất cả các số đều có định dạng 64 bit chính xác kép (giá trị IEEE 754), ngay cả khi một số toán tử hoạt động nội bộ với các giá trị Số nguyên (như toán tử bit) kết quả luôn là gấp đôi . Trong 'i'ví dụ này xuất phát từ undefined, nhưng nó có thể đến từ Infinityví dụ: (+!+[]/+[+[]]+[])[!+[]+!+[]+!+[]]=> (1/0+'')[3]=> (Infinity+'')[3]=>'i'
CMS

5
@JoshStodola Vâng, ~ 3 tháng sau, một sự sáng tỏ thêm. Chữ "i" trong trường hợp này xuất phát từ "không xác định", đúng vậy, nhưng có một thủ thuật khác liên quan ở đây. Đoạn mã nối "false" với "undefined" để tạo thành "falseundefined"(được xây dựng bằng cách sử dụng [![]]+[][[]]:) trong đó chỉ số của "i" là 10. +!+[]+[+[]]cho "10". Điều này được sử dụng để trích xuất "i" (Chỉ số chuỗi có thể được sử dụng trong javascript nếu chúng có thể được ép buộc thành số nguyên). Các cấu trúc chính thức trong đó sản xuất đó là:([![]]+[][[]])[+!+[]+[+[]]]
entropy
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.