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ì?
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ì?
{
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.
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;
-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
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ò. –
Aye. Tôi hủy bỏ phiếu bầu của tôi. – roosteronacid
Đơ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.
JavaScript của nó ... đối phó với nó. –
Thú vị, nhưng chính xác thì mục đích đó là gì? –
hm, 'false == {}' evals đến 'false' trong Firefox 3.5.3 – SilentGhost