2009-10-02 47 views
15

Trong Firefox 3.5, tôi gõ này trong Firebug console:JavaScript: {} == false là một Cú pháp Cú pháp?

false=={} // => evals to false 
{}==false // syntax error 

lời giải thích cho điều này là gì?

+19

JavaScript của nó ... đối phó với nó. –

+1

Thú vị, nhưng chính xác thì mục đích đó là gì? –

+2

hm, 'false == {}' evals đến 'false' trong Firefox 3.5.3 – SilentGhost

Trả lời

41
{ 

vào lúc bắt đầu của một tuyên bố các tín hiệu một 'khối tuyên bố' (xem ECMA-262-3 phần 12.1), trong đó có một danh sách các câu lệnh.

} 

ngay lập tức kết thúc khối câu lệnh mà không có câu lệnh nào trong đó. Đó là tốt. Nhưng bây giờ trình phân tích cú pháp đang tìm kiếm câu lệnh tiếp theo:

==false 

Huh? Đó không phải là một tuyên bố; lỗi cú pháp.

Khối tuyên bố là gì?Vâng, bạn đang viết một khối tuyên bố mỗi khi bạn nói:

if (something) { 
    ... 
} 

Javascript xác định các báo cáo lưu lượng kiểm soát như:

if "(" <expression> ")" <statement> [else <statement>] 

tức. trong biểu mẫu tuyên bố đơn lẻ không có niềng răng. Sau đó nó cho phép bạn sử dụng một khối lệnh bất cứ nơi nào bạn có thể sử dụng một câu lệnh đơn, có nghĩa là bạn có thể có các câu lệnh if-niềng răng-nhiều câu lệnh. Nhưng nó cũng có nghĩa là bạn có thể tự mình có một khối tuyên bố mà không có câu lệnh kiểm soát dòng chảy liên quan.

Điều này hoàn toàn không có mục đích thiết thực! Bạn có thể bị cám dỗ để nghĩ rằng nó đã cho bạn thông tin ẩn, nhưng không có:

var a= 1; 
{ 
    var a= 2; 
} 
alert(a); 

... kết quả trong 2, bởi vì khối tuyên bố không trong bản thân mình tạo ra một phạm vi mới.

JavaScript xác định luồng điều khiển và khối câu lệnh theo cách này vì C (và các ngôn ngữ khác bắt nguồn từ nó) đã làm. Tuy nhiên, những ngôn ngữ đó không làm cho {} phục vụ nhiệm vụ kép như là một biểu thức của Đối tượng, vì vậy chúng không có sự mơ hồ làm cho sự khác biệt này của JS.

Thậm chí này Wannabe-đen:

{ 
    a: 1 
} 

là một khối tuyên bố hợp lệ, bởi vì ‘:’ được sử dụng để biểu thị một nhãn trong một tuyên bố. (và 1 là một tuyên bố biểu thức vô dụng, với dấu chấm phẩy bị bỏ qua.) Nhãn là một tính năng khác được kế thừa từ C hiếm khi được sử dụng trong JavaScript. Chúng không hoàn toàn vô nghĩa như các khối, nhưng chúng hiếm khi cần thiết và thường được xem là có mùi vị kém.

(A đen với hai thuộc tính sẽ gây ra một lỗi cú pháp, là dạng đối tượng sử dụng dải phân cách dấu phẩy, nhưng dán nhãn báo cáo phải được phân cách bằng dấu chấm phẩy.)

Đây là not the only place nơi cú pháp lỏng lẻo JavaScript có thể vấp bạn lên bằng cách làm một số tuyên bố khác của một cái gì đó bạn nghĩ là một biểu thức.

+0

Và ({}) == công trình sai. –

+0

Có, và! {} == đúng cũng hoạt động! – glmxndr

+4

có và trứng!== củ cải đường cũng là sai, bởi vì bạn có thể đánh bại và trứng nhưng bạn không thể đánh bại một gốc. – Evernoob

11

OK, tôi đã nghiên cứu ECMAScript specification (PDF) và tôi có giải thích cho phép từ chối BNF grammar.

nguồn ECMAScript được phân tích cú pháp bắt đầu với biểu tượng chính, được gọi là Program:

Program: 
    SourceElements 

SourceElements' (recursive) định nghĩa là thế này:

SourceElements : 
    SourceElement 
    SourceElements SourceElement 

Các, SourceElement được định nghĩa là:

SourceElement : 
    Statement 
    FunctionDeclaration 

Điều chúng tôi quan tâm là cú pháp ngữ pháp đối tượng, vì vậy chúng tôi bỏ qua FunctionDeclaration và nhìn vào Tuyên bố biểu tượng:

Statement : 
    Block 
    VariableStatement 
    EmptyStatement 
    ExpressionStatement 
    IfStatement 
    IterationStatement 
    ContinueStatement 
    BreakStatement 
    ReturnStatement 
    WithStatement 
    LabelledStatement 
    SwitchStatement 
    ThrowStatement 
    TryStatement 

Tôi không chắc chắn nếu những vấn đề niêm yết trật tự (đây là cách họ đang có trong spec), nhưng ... một đối tượng theo nghĩa đen là một ExpressionStatement, về những tiêu chuẩn nói như sau (phần 12,4):

Lưu ý rằng một ExpressionStatement không thể bắt đầu với một khe hở xoăn cú đúp, vì đó có thể làm cho nó mơ hồ với một Block. Ngoài ra, một ExpressionStatement không thể bắt đầu bằng từ khóa chức năng vì điều đó có thể làm cho nó mơ hồ với một FunctionDeclaration.

Vì vậy, chúng tôi có thể có một biểu vào lúc bắt đầu của chương trình, nhưng nó không phải bắt đầu với một cú đúp xoăn mở ({). Đó là lý do tại sao công việc OK sau:

  • ({} == false);
  • alert({} == false);
  • !{} == false;
+0

-1 Không phải là một câu trả lời thực sự (.. hoặc có lẽ tôi chỉ không nhận được quan điểm của bạn). Hãy soi sáng cho tôi :) – roosteronacid

+0

Bạn hoàn toàn đúng. Thay vào đó là một giải pháp thay thế. Tôi đang tìm kiếm thông qua đặc tả ECMAScript 3 để tìm câu trả lời thực sự. Tôi cũng tò mò. –

+0

Aye. Tôi hủy bỏ phiếu bầu của tôi. – roosteronacid

0

Đơn giản chỉ cần nói, {}==false được biên dịch bởi trình biên dịch Js thành {};==false, do đó, đó là lỗi cú pháp. bạn nên viết ({})==false và nó sẽ trả về false.

Các vấn đề liên quan