Cách xử lý ngắt dòng của Python khác với dấu chấm phẩy tự động của JavaScript như thế nào?


41

Javascript có một tính năng gọi là Chèn dấu chấm phẩy tự động trong đó về cơ bản nếu trình phân tích cú pháp gặp mã thông báo không hợp lệ và mã thông báo cuối cùng trước đó là ngắt dòng, thì trình phân tích cú pháp sẽ chèn dấu chấm phẩy nơi ngắt dòng. Điều này cho phép bạn về cơ bản viết tất cả mã javascript của bạn mà không có dấu chấm phẩy, nhưng bạn phải biết một số trường hợp cạnh, chủ yếu là nếu bạn có một từ khóa trả về và sau đó là giá trị bạn muốn trả về trên một dòng mới.

function test(){
    // This will return 'undefined', because return is a valid statement
    // and  "john" is a valid statement on its own.
    return 
          "john"
}

Bởi vì những vấn đề này, có hàng tá bài viết với tiêu đề như 'Tự động chèn dấu chấm phẩy là Ác quỷ', 'Luôn sử dụng dấu chấm phẩy trong Javascript', v.v.

Nhưng trong Python không ai từng sử dụng dấu chấm phẩy và nó có chính xác các vấn đề tương tự.

def test():
    # This will return 'undefined', because return is a valid statement
    # and  "john" is a valid statement on its own.
    return 
    "john"

Hoạt động giống hệt nhau, nhưng không ai sợ chết khiếp hành vi của Pythons.

Tôi nghĩ rằng các trường hợp javascript hoạt động kém là đủ để bạn có thể tránh chúng dễ dàng. Trả về + giá trị trên một dòng mới? Mọi người có thực sự làm điều đó rất nhiều?

Có ý kiến ​​gì không? Bạn có sử dụng dấu chấm phẩy trong javascript không và tại sao?


3
Nó không hoạt động chính xác như nhau. Việc chèn dấu chấm phẩy không đi đến đâu trong dòng mới, nhất thiết, trong JavaScript. Xem ví dụ thứ hai trên trang Wikipedia này . Dấu chấm phẩy không được chèn trong đó dòng mới nằm trong ví dụ đó.
Reid

1
Quan điểm của tôi không phải là sử dụng dấu chấm phẩy và không sử dụng chúng hoạt động giống hệt nhau, vấn đề là các trường hợp cạnh trong javascript và python là như nhau. Chắc chắn có một vài trường hợp cạnh mà bạn phải biết những gì đang xảy ra. Bài viết hay nhất tôi đã đọc về chủ đề này: inimino.org/~inimino/blog/javascript_semiaolons
Einar Egilsson

4
Tôi đặt dấu chấm phẩy trong JavaScript vì lý do tương tự tôi sử dụng dấu chấm trong câu. Chắc chắn thông dịch viên thường có thể hiểu ý của bạn mà không có chúng nhưng nó chỉ là hình thức xấu.
JD Isaacks

3
Bạn có thể xem xét việc viết python hợp lệ trong các ví dụ của bạn. Chỉ báo nhận xét là #, không phải `// '.
Aaron Dufour

2
"

Câu trả lời:


62

Lý do là trong Python, các dòng mới là một cách rõ ràng để phân tách các dòng mã; Đây là do thiết kế, và cách thức hoạt động của công trình này đã được suy nghĩ thấu đáo. Kết quả là, mã python hoàn toàn dễ đọc và rõ ràng mà không có bất kỳ dấu hiệu kết thúc đặc biệt nào (ngoài dòng mới).

Javascript, mặt khác, được thiết kế với một cú pháp giống như C, trong đó các câu lệnh luôn được chấm dứt bằng dấu chấm phẩy. Để làm cho ngôn ngữ trở nên dễ chịu hơn đối với các lỗi, nó cố gắng đoán xem dấu chấm phẩy bổ sung sẽ đi đến đâu để làm cho mã chính xác. Vì đây là loại được trang bị theo cú pháp retro cho cú pháp giống như C, nên nó không hoạt động như mong đợi (đôi khi, trình thông dịch kịch bản đoán sai) và có thể tạo mã tương đối trực quan. \

Hoặc, tranh luận về mặt "rõ ràng tốt hơn ngầm định": Trong Python, một dòng mới đã hoàn toàn rõ ràng, trong khi trong Javascript, nó không rõ ràng, vì vậy bạn thêm dấu chấm phẩy để làm cho nó rõ ràng.


3
Ồ, và bạn có thể đặt mã trong các bình luận bằng cách sử dụng backquotes.
tdammers

1
Một ví dụ điển hình về trường hợp chèn nửa dấu chấm tự động sẽ kết thúc những việc không mong muốn là: pastebin.com/aVeWGdya
HoLyVieR

5
Trong python, các quy tắc khá đơn giản: các câu lệnh kết thúc khi ngắt dòng trừ khi có một chuỗi đa dòng không được tiết lộ ("" ", '' '), một lệnh không được tiết lộ ({}), một danh sách không được tiết lộ ([]) hoặc dấu gạch chéo ngay lập tức trước khi phá vỡ dòng. Trong javascript, các quy tắc phức tạp hơn đáng kể.
Aaron Dufour

5
Bao phủ 99% lỗi là một cách tốt để chỉ để lại những lỗi thực sự khó tìm. Không sao để lại chúng trong python vì có những quy tắc dễ dàng bao gồm 100% vấn đề.
Aaron Dufour

1
@Aaron: Bạn đã quên "một bộ dấu ngoặc đơn chưa được tiết lộ (())". (Không đúng "một tuple không khép kín" vì ngoặc không chỉ được sử dụng cho các bộ.)
JAB

28

Có một sự khác biệt khá cơ bản so với cách nó hoạt động trong Python, tôi nghĩ vậy. Trích dẫn từ bài Einar Egilsson được liên kết đến: "dấu chấm phẩy không được ngụ ý ở cuối dòng nếu mã thông báo đầu tiên của dòng tiếp theo có thể được phân tích cú pháp như một phần của cùng một tuyên bố".

Trong Python, ngắt dòng luôn kết thúc câu lệnh, ngoại trừ trong một số trường hợp khá rõ ràng như trong biểu thức được ngoặc đơn. Mặt khác, JavaScript sẽ cố phân tích nhiều dòng nhất có thể trước khi kết thúc câu lệnh, có khả năng dẫn đến những thứ như thế này:

// Define a function and name it area.
area = function(r) {
    return r * r * 3.14159
}

// Fooled you! We're actually invoking it.
(14)

8
Bây giờ đây là một twist thú vị về điều này. Thay thế 14 bằng một cái gì đó giống (a + 1) ? do_something() : do_something_else();và đột ngột, khu vực được đặt thành giá trị trả về của do_something()hoặc do_something_else()bạn có thể bị nhầm lẫn.
Reid

20

Tôi thường thu nhỏ các tệp JS của mình trong chế độ sản xuất. Có nghĩa là, loại bỏ ý kiến ​​và ngắt dòng.

Nếu không sử dụng dấu chấm phẩy, điều đó sẽ phá vỡ Javascript của tôi.


8
OK, hợp lệ. Nhưng nếu trình thu nhỏ của bạn là một trình phân tích cú pháp thực tế thì nó có thể chèn lại chúng khi cần thiết. Hoặc chỉ không xóa các ngắt dòng, => bạn giữ các ngắt dòng, mất dấu chấm phẩy, chúng gần bằng nhau nên không có gì bị mất.
Einar Egilsson

2
@Einar Egilsson Đóng trình biên dịch thực sự làm điều này.
Severdev

1
Tất cả mọi thứ đều bằng nhau, một dòng mới có cùng số byte như một dấu chấm phẩy. Bộ thu nhỏ của bạn có thể loại bỏ tất cả các dòng mới, nhưng sau đó yêu cầu phải có dấu chấm phẩy. Đó là một cuộc trao đổi thậm chí.
Logan Bailey

3
@Logan: Tất nhiên là giả sử một dòng mới byte ;-)
Cameron

1
Tất nhiên, nếu chúng ta sử dụng Python thay vì Javascript, chúng ta sẽ phải viết mã CÁCH ít hơn để làm điều tương tự, vì vậy thực tế là các dấu chấm phẩy sử dụng ít hơn một vài byte so với thụt lề là một điểm cần thiết.
BlueRaja - Daniel Pflughoeft

5

Nó không hoạt động như bạn mô tả.

Javascript có một tính năng gọi là Chèn dấu chấm phẩy tự động trong đó về cơ bản nếu trình phân tích cú pháp gặp mã thông báo không hợp lệ và mã thông báo cuối cùng trước đó là ngắt dòng, thì trình phân tích cú pháp sẽ chèn dấu chấm phẩy nơi ngắt dòng.

Cái này sai. Thí dụ:

return
  1 + 2;

1là một mã thông báo hoàn toàn hợp lệ, nhưng trình phân tích cú pháp vẫn sẽ chèn dấu chấm phẩy trực tiếp sau đó return.

Như bạn thấy, thậm chí bạn không thể biết chính xác nơi dấu chấm phẩy sẽ xảy ra.

Vấn đề với chèn tự động là gấp đôi:

  • Đối với một người, mọi người có thể bỏ dấu chấm phẩy trong đó việc chèn tự động không thể xác định rằng cần phải chèn.
  • Ngoài ra, một dấu chấm phẩy có thể được chèn vào nơi không có ý định, như trên.

Tất nhiên, sử dụng dấu chấm phẩy sau mỗi câu lệnh chỉ giúp với nguồn lỗi đầu tiên.

Trong mọi trường hợp, như bạn có thể đoán bây giờ, tôi tin rằng việc chèn dấu chấm phẩy tự động trong cú pháp giống như C là một ý tưởng tồi.


1
ECMA Script chỉ định rõ ràng chỉ định trường hợp nào dấu chấm phẩy sẽ được chèn, do đó dòng của bạn "Bạn không thể biết chính xác nơi dấu chấm phẩy sẽ xảy ra" là không chính xác. Vấn đề là nó không trực quan trong một số trường hợp, khiến cho việc dạy một người không hiểu cách thức hoạt động của nó trở nên khó khăn hơn.
zzzzBov

1
@zzzzBov: Vâng, có một đặc điểm kỹ thuật chính xác, nhưng có ai thực sự có tất cả các trường hợp trong tâm trí khi viết mã không? Bạn có chắc không? Các lập trình viên lười biếng, và đúng như vậy; họ không muốn phải nhớ một quy tắc phức tạp khi một quy tắc đơn giản hơn nhiều sẽ làm. Vì vậy, họ cố gắng để có được xung quanh phải nhớ nó.
Svante

Tôi đồng ý rằng chèn nửa đại tràng phần lớn là không cần thiết. Tôi chỉ nói có một sự khác biệt giữa việc nói "bạn không biết bán đại tràng đang đi đâu" và "thông số kỹ thuật cho việc chèn dấu hai chấm là một mớ bòng bong không trực quan"
zzzzBov

1
@Svante: Nhưng ví dụ trả về cho chúng ta thấy rằng chúng ta phải biết các quy tắc này. Ở đó bạn đã sử dụng một dấu chấm phẩy nhưng nó không giúp bạn làm những gì bạn muốn. Vì vậy, do ngôn ngữ có tính năng này, chúng tôi có tùy chọn (1) Viết dấu chấm phẩy ở mọi nơi và biết các quy tắc để chúng tôi hiểu điều gì sẽ xảy ra (2) Không viết dấu chấm phẩy ở mọi nơi và hiểu quy tắc để chúng tôi hiểu điều gì sẽ xảy ra. Đưa ra lựa chọn đó, tôi nghĩ rằng tôi muốn bỏ qua dấu chấm phẩy
Einar Egilsson

4

Tôi muốn nêu một lý do đơn giản:

Javascript có vẻ "kinda java-ish" hoặc "kinda C-ish". Tất nhiên đó là một ngôn ngữ năng động để nó trông khác ... nhưng phải đối mặt với nó - Có niềng răng. Ngôn ngữ với niềng răng thường có dấu chấm phẩy. Các phản xạ tự nhiên đá vào và làm cho ngón tay của bạn đi về phía phím dấu chấm phẩy trước khi bạn nhấn Enter.

Python, ngược lại, thậm chí trong nháy mắt trông hoàn toàn khác nhau. Do đó, ít hoặc không có sự tương tự với "ngôn ngữ nhàm chán tiêu chuẩn" được hình thành bằng trực giác và khi một người bước vào "chế độ python", việc thiếu dấu chấm phẩy là điều đương nhiên.


2

Có một số tốt lý do không để chèn sử dụng dấu chấm phẩy trong JavaScript.

Chủ yếu là bởi vì chèn nửa dấu hai chấm như được định nghĩa trong tiêu chuẩn ECMAScript là không trực quan đối với một số trường hợp. @Svante chỉ ra một trường hợp trong returnđó việc sử dụng dòng mới sẽ gây ra vấn đề.

Điều anh ấy không đề cập là nó cũng sẽ gây ra vấn đề nếu bạn cũng đang sử dụng dấu chấm phẩy, bởi vì việc chèn dấu hai chấm xảy ra cho dù bạn có muốn hay không.

Một lý do rất tốt khác để không sử dụng chèn nửa dấu hai chấm là kiểm soát đầu ra. Trong nhiều trường hợp, JavaScript được chạy qua một công cụ khai thác trước khi được sử dụng trong sản xuất. Một số công cụ khai thác có thể xử lý các trường hợp chèn dấu chấm phẩy tự động, nhưng tôi thấy không có lý do gì để dựa vào nó hoạt động hoàn hảo

Ngoài ra, đối với các hệ thống quản lý nội dung, JavaScript nội tuyến có thể được tự động thu nhỏ và tôi đã thấy một số trường hợp trong đó công cụ khai thác tự động chỉ cần xóa các nhận xét và cắt khoảng trắng (bao gồm cả dòng mới) từ đầu và cuối của mỗi dòng.

Đối với các tác giả không có lựa chọn công cụ nào đang được chọn, việc sử dụng định dạng hoạt động trong phần lớn các trường hợp sẽ dễ dàng hơn nhiều.


À, xin lỗi, nhưng liên quan đến đoạn thứ ba của bạn, tôi đề cập đến điều đó trong câu thứ hai đến câu cuối của tôi. :)
Svante

Có, vấn đề công cụ là hợp lệ (mặc dù các công cụ khai thác tốt sẽ xử lý việc này, ví dụ Trình biên dịch đóng). Nhưng theo tôi, dù sao chúng ta cũng cần biết những quy tắc này, để tránh những điều như ví dụ 'trở về'. Và một khi tôi biết các quy tắc, tôi cũng có thể sử dụng tính năng này, đặc biệt là vì nó làm cho mã (IMO) dễ đọc hơn.
Einar Egilsson

1

Không sử dụng dấu chấm phẩy là một công thức cho sự thất bại khi bạn thu nhỏ các tệp JavaScript của mình. Đó là lý do tại sao tôi sợ nó.


1

Trong Javascript, bạn có thể viết một chương trình mà sẽ là cú pháp đúng trong trường hợp không chèn dấu chấm phẩy tự động, và ASI sẽ làm thay đổi chương trình đó vào một khác nhau chương trình đúng cú pháp (ví dụ, chuyển mã mà trả về một giá trị vào mã mà lợi nhuận không có gì). Không có trường hợp tương tự trong Python. Trong Python, bất kỳ dòng mới nào có thể kết thúc một câu lệnh sẽ kết thúc một câu lệnh, trừ khi nó được thoát bằng dấu gạch chéo ngược. Về mặt kỹ thuật, tôi cho rằng các quy tắc của Javascript có tính quyết định như nhau, nhưng tôi không biết liệu bạn có thể tóm tắt các quy tắc của Javascript để kết thúc các câu trong một câu không.


1

Trong hầu hết các trường hợp, ASI của JavaScript xử lý mọi thứ như mong đợi. Một ví dụ về ASI có lẽ không hành xử theo cách bạn mong đợi là:

var i = 0

(function() {
   // do something
})()

Điều này sẽ được hiểu là gọi hàm 0với hàm ẩn danh, sau đó thực hiện kết quả. Trong trường hợp này, bạn có thể muốn thực hiện một nhiệm vụ, sau đó thực hiện ngay chức năng ẩn danh.

Đối với một người không quen thuộc với ASI, có thể rất khó hiểu khi bạn gặp phải các vấn đề như thế này, vì vậy tôi luôn khuyên các nhà phát triển trong nhóm của tôi sử dụng dấu chấm phẩy.

(Về một bên: Tôi không sử dụng dấu chấm phẩy khi làm việc trên các dự án cá nhân / phụ vì tôi biết không ai khác sẽ cần phải duy trì mã.)


1

Giống như bạn, tôi nghĩ đó là một chút hoang tưởng. Các quy tắc để chèn dấu chấm phẩy được xác định rõ trong JavaScript, giống như chúng có trong Python và CoffeeScript. Không ai phát hành Python hoặc CoffeeScript bằng dấu chấm phẩy, vậy tại sao JavaScript lại được xử lý khác nhau?

Tôi nghĩ rằng đó là một phản ứng thái quá đối với trạng thái tồi tệ của mã JavaScript điển hình từ khoảng mười năm trước, JavaScript JavaScript được xem là một ngôn ngữ yếu, lỗi, xấu, không tốt. Đó là một sự bối rối. Bạn không thể viết mã tốt bằng JavaScript!

Sau đó, mọi người xuất hiện và cố gắng chứng minh rằng bạn có thể viết mã đẹp, rõ ràng bằng JavaScript. Quy tắc " luôn luôn sử dụng dấu chấm phẩy" là một phần của làn sóng này. Và thành thật mà nói, nó có thể làm cho một vài tình huống rõ ràng hơn một chút.

Tại sao JavaScript vẫn được xử lý khác nhau?

Có quán tính. Và không nên bỏ qua rằng những người đánh giá cao mã có cấu trúc rõ ràng thường thích ngôn ngữ kiểu C. Những người đánh giá cao mã có cấu trúc ngầm thường chuyển sang các ngôn ngữ không phải kiểu C (như CoffeeScript).


0

Tôi sử dụng chúng trong Javascript một cách nghiêm ngặt để thống nhất. Nếu hầu hết các dòng có

Python có chúng cho các trường hợp cạnh như nhiều câu lệnh trên một dòng, javascript có chúng và vì bạn sẽ thấy chúng được sử dụng thường xuyên, tôi tuân thủ quy tắc nơi chúng được sử dụng.

Tôi không thể tìm thấy việc sử dụng cho nhiều câu lệnh trên cùng một dòng và do đó không thấy trước khi sử dụng dấu chấm phẩy.


Có, tôi đã sửa ví dụ Python. Nhưng vấn đề vẫn còn, Python cũng có dấu chấm phẩy, bạn có thể đặt chúng sau mỗi câu lệnh (và phải nếu bạn có nhiều hơn một dòng trên mỗi dòng) nhưng mọi người không sử dụng chúng.
Einar Egilsson

0

Nếu bạn sử dụng một cái gì đó như bundle-fu và trình quản lý tài sản cho ứng dụng web của bạn, thì nó sẽ bị hỏng một cách khủng khiếp nếu nó không gặp dấu chấm phẩy ở cuối mã thông báo trong javascript. Vì vậy, đó là một thực hành tốt để đặt một.


Vâng, ba máy nén lớn YUI, Trình biên dịch đóng cửa và UglifyJS, tất cả đều thực hiện chèn dấu chấm phẩy. Tôi không ngạc nhiên khi cổng ruby ​​của JSMin có vấn đề.
Benjamin Atkin

0

Tôi không thể nhớ phiên bản chính xác nào của IE, nhưng có một số trường hợp IE sẽ bị lỗi theo nghĩa đen nếu thiếu dấu chấm phẩy. IIRC đó là khi bạn có trong phạm vi toàn cầu, đại loại như:

var myFunc = function() {
  ...
}

Nếu bạn không thêm; sau khi kết thúc, chương trình sẽ thực sự thất bại trên một số phiên bản IE. Điều đó, cùng với các lý do khác (bao gồm khuyến nghị của Crockford là luôn sử dụng chúng một cách rõ ràng) đã khiến tôi luôn luôn sử dụng chúng một cách rõ ràng trong mọi trường hợp.

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.