Tại sao 0.-5 đánh giá thành -5?


84

Giả sử tôi viết 0.5theo 0.-5cách không mong muốn, nhưng nó vẫn có thể chạy. Cái gì0. tại 0.-5làm như vậy mà nó vẫn có thể chạy và đánh giá lại đến -5?

Tôi cũng đã cố gắng alert(0.-5+1)mà in -4, không bỏ qua JavaScript 0.trong 0.-5?


55
0.giống như 0.0. Hoặc chỉ 0.
Ry-

61
Điều gì khiến bạn nghĩ rằng đó 0.-5là một "cách bất ngờ"?
Nico Haase,

15
@NicoHaase: Tôi khá chắc chắn rằng OP đã sử dụng "cách bất ngờ" có nghĩa là "Tôi không có ý định / mong đợi viết điều đó, nhưng bằng cách nào đó tôi đã làm".
Filip Milovanović

15
Điều này cũng hoạt động trên nhiều ngôn ngữ khác (ví dụ: Python). Cá nhân tôi không thích nó chút nào. Tôi thà có 0.-5lỗi cú pháp và không cho phép ký tự float với dấu .0chấm nhưng buộc mọi người phải viết ở cuối.
Giacomo Alzetta

9
Đó là đặc biệt xấu vì phép số kết thúc vào .ngăn bạn viết một cái gì đó giống như 123.toString(16)(A lừa phổ biến là sử dụng 123..toString(16), đó là thực sự (123.).toString(16))
12Me21

Câu trả lời:


191

Các chữ số ở cuối sau a .là tùy chọn:

console.log(0. === 0); // true

Vì thế

0.-5

đánh giá

0 - 5

mà chỉ là -5. Tương tự,

0.-5+1

0 - 5 + 1

đó là

-5 + 1

hoặc -4.


16
Các chữ số hàng đầu cũng là tùy chọn, vì vậy .0-5 cũng hợp lệ
icenac

48

0.-5có thể được phân tích thành công như 0.[1] , -5. Dưới đây là cây cú pháp trừu tượng cho biểu thức được tạo bởi AST explorer:

Cây phân tích cú pháp được tạo bởi AST explorer

Đây (theo cách không mong muốn) là JavaScript hợp lệ và được đánh giá là -5.


[1] Theo ngữ pháp cho các chữ số, các chữ số thập phân và phần lũy thừa là tùy chọn:

NumericLiteral ::
  DecimalLiteral
  [...]

DecimalLiteral ::
  DecimalIntegerLiteral. DecimalDigits opt ExponentPart opt


bạn đã trích xuất AST như thế nào?
Κωλζαρ

8
Tới astexplorer.net , chọn một ngôn ngữ và một phân tích cú pháp, dán mã, chọn ra JSON (hoặc chỉ cần mất một ảnh chụp màn hình).
Salman A

39

Trong JS, bạn có thể biểu thị một số với dấu thập phân tùy chọn.

x = 5.;    //5
x = 5. + 6.   //11

Và theo nhận xét của Tvde1, bất kỳ phương pháp Số nào cũng có thể được áp dụng.

5..toString()

Cú pháp này cho phép chúng ta chạy các hàm Số không có dấu ngoặc đơn.

5.toString() //error
(5).toString() //good
5..toString() //good
5 .toString() // awesome

Xem câu hỏi này để tìm hiểu tại sao.


4
Bạn thậm chí có thể làm 5..toString().
Tvde1

2
Nếu trên thực tế, bạn phải làm 5..toString () để gọi phương thức, nếu không, bạn phải sử dụng dấu ngoặc đơn: (5) ToString ()
jo_va

3
@PeterMortensen Ruby, cho một. Ngoài ra ALGOL 68. Trong Common Lisp, kỳ lạ thay, 1.0là dấu phẩy động nhưng 1.là một số nguyên.
Sneftel

2
@FlorianF Bạn sẽ không, nhưng điều đó không có nghĩa là trình phân tích cú pháp phải được đặc biệt hóa để từ chối nó. floats có các phương thức, và 5.là một float.
chepner 25/02/19

2
@MasonWheeler Chắc chắn không phải là trường hợp bất kỳ ngôn ngữ nào khác (1).toMethod()được pháp luật cấm (1.)phân tích cú pháp đúng cách. Cách tiếp cận truyền thống nhất để phân tích cú pháp (ghép nối tham lam các mã thông báo, bao gồm cả các ký tự, sau đó phân tích cú pháp) tạo ra hành vi Javascript.
Sneftel

7

Tôi sẽ nghĩ rằng câu trả lời thực sự không phải về dấu thập phân, mà là về dấu trừ: điều đó sẽ không được hiểu như một toán tử nếu nó được đặt trước bất kỳ thứ gì giống như một số?


1
Sau đó, ít nhất trong một số quan điểm, nó vẫn về việc dấu thập phân được hiểu là một phần của chữ số, nếu không, những gì đứng trước dấu trừ sẽ không "trông giống như một số".
Pac0

5

console.log(0. - 5)      // -5
console.log(0 - 5)       // -5
console.log('0.' - 5)    // -5
console.log('0' - 5)     // -5
console.log(0.-5 === -5) // true

'0.' hoặc '0' giống nhau trong JavaScript vì kiểu là duy nhất cho các số, được gọi là Số. Toán tử trừ nằm giữa Số, luôn cố gắng chuyển những gì bạn chuyển thành Số. Trong Python thì khác, đầu tiên là Float và thứ hai là Integer vì nó có một số kiểu.


Vấn đề này không liên quan đến các loại; nó chỉ liên quan đến cú pháp.
user4642212
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.