JavaScript có được giải thích theo thiết kế không?


73

Tôi thận trọng khi đặt câu hỏi này vì nó có vẻ quá khó tính. Tôi vừa mở JavaScript: Hướng dẫn dứt khoát và nó nêu lên trang đầu tiên của chương 1

"JavaScript là ngôn ngữ lập trình được giải thích ở mức độ cao, năng động, chưa được kiểm tra

Vì vậy, tôi có thể cho rằng phần được diễn giải là một yêu cầu trong đặc tả ngôn ngữ, hay là sai lầm khi nói rằng ngôn ngữ là ngôn ngữ lập trình được giải thích khi tôn trọng sự khác biệt giữa một ngôn ngữ và nhiều cách triển khai của nó?

Rõ ràng không có trình biên dịch tĩnh cho JavaScript - https://stackoverflow.com/questions/1118138/is-there-a-native-machine-code-compiler-for-javascript vì vậy có lẽ đó chỉ là sự phản ánh của điều này.


Có một jscript.net trong một thời gian tương tự như AS3 / ES4 "mất". Nó được biên dịch bằng mã byte cho CIL.
Này

13
V8 tuyên bố rõ ràng không phải là một thông dịch viên mà là một trình biên dịch.
pimvdb

@GGG JScript.Net vẫn còn sống và ... ốm yếu. Nhưng vẫn còn sống. msdn.microsoft.com/en-us/l
Library / 72bd815a.aspx

1
FWIW, bit "chưa được xử lý" cũng không hoàn toàn đúng
Rob Agar

Firefox vừa phát hành trình biên dịch JIT dựa trên trình duyệt đầu tiên vào năm mà câu hỏi đã được trả lời trong FF 3.5 nên có lẽ nó không được biết đến rộng rãi vào thời điểm đó. Tôi tin rằng các JIT hiện đại thực sự thực hiện rất nhiều việc biên dịch (hoặc ít nhất là chuẩn bị cho việc biên dịch) trong lần đầu tiên của tài liệu JS để thực hiện những việc như xác định và các phương thức bộ đệm được tách biệt trong một phạm vi nhất định.
Erik Reppen

Câu trả lời:


50

Vì vậy, tôi có thể cho rằng phần được diễn giải là một yêu cầu trong đặc tả ngôn ngữ, hay là sai lầm khi nói rằng ngôn ngữ là ngôn ngữ lập trình được giải thích khi tôn trọng sự khác biệt giữa một ngôn ngữ và nhiều cách triển khai của nó?

Các chuyên viên máy tính ngôn ngữ EcmaScript thường sử dụng thuật ngữ "Trình thông dịch ES" để chỉ việc triển khai EcmaScript, nhưng thông số kỹ thuật không sử dụng thuật ngữ đó. Các tổng quan về ngôn ngữ đặc biệt mô tả các ngôn ngữ về thông dịch-agnostic:

ECMAScript dựa trên đối tượng: ngôn ngữ cơ bản và phương tiện lưu trữ được cung cấp bởi các đối tượng và chương trình ECMAScript là một cụm các đối tượng giao tiếp.

Vì vậy, EcmaScript giả định một "môi trường máy chủ" được định nghĩa là nhà cung cấp các định nghĩa đối tượng bao gồm tất cả các liên kết cho phép I / O hoặc bất kỳ liên kết nào khác với thế giới bên ngoài, nhưng không yêu cầu trình thông dịch.

Các ngữ nghĩa của các câu lệnh và biểu thức trong ngôn ngữ được định nghĩa theo các đặc điểm kỹ thuật hoàn thành được thực hiện một cách tầm thường trong một trình thông dịch, nhưng đặc tả không yêu cầu điều đó.

8,9 Loại đặc tả hoàn thành

Các loại Hoàn thành được sử dụng để giải thích hành vi của báo cáo ( break, continue, returnthrow) mà thực hiện chuyển không cục bộ tầm kiểm soát. Các giá trị của loại Hoàn thành là bộ ba của biểu mẫu ( loại , giá trị , mục tiêu ), trong đó loại là một trong các giá trị bình thường , phá vỡ , tiếp tục , trả lại hoặc ném , giá trị là bất kỳ giá trị ngôn ngữ ECMAScript hoặc trốngmục tiêu là bất kỳ định danh ECMAScript nào hoặc rỗng .

Thuật ngữ hoàn thành đột ngột, đề cập đến bất kỳ sự hoàn thành nào với một loại khác hơn bình thường .

Việc chuyển điều khiển không cục bộ có thể được chuyển đổi thành các mảng hướng dẫn với các bước nhảy cho phép biên dịch mã gốc hoặc mã byte.

"Công cụ EcmaScript" có thể là một cách tốt hơn để diễn đạt cùng một ý tưởng.


Không có trình biên dịch tĩnh cho JavaScript rõ ràng

Đây không phải là sự thật. "Trình thông dịch" V8 biên dịch thành mã gốc bên trong, Rhino tùy ý biên dịch sang mã byte Java bên trong và nhiều trình thông dịch Mozilla khác nhau ({Trace, Spider, Jager} Monkey) sử dụng trình biên dịch JIT.

V8 :

V8 tăng hiệu suất bằng cách biên dịch JavaScript thành mã máy gốc trước khi thực thi nó, so với thực thi mã byte hoặc giải thích nó.

Tê giác :

public final void setOptimizationLevel(int optimizationLevel)

Đặt mức tối ưu hóa hiện tại. Mức tối ưu hóa được dự kiến ​​là một số nguyên nằm trong khoảng -1 đến 9. Mọi giá trị âm sẽ được hiểu là -1 và mọi giá trị lớn hơn 9 sẽ được hiểu là 9. Mức tối ưu hóa -1 cho biết chế độ diễn giải sẽ luôn luôn là đã sử dụng. Cấp độ 0 đến 9 chỉ ra rằng các tệp lớp có thể được tạo. Các mức tối ưu hóa cao hơn đánh đổi hiệu năng thời gian biên dịch cho hiệu năng thời gian chạy. Mức tối ưu hóa không thể được đặt lớn hơn -1 nếu gói tối ưu hóa không tồn tại trong thời gian chạy.

TraceMonkey :

TraceMonkey bổ sung quá trình biên dịch mã gốc vào công cụ JavaScript® của Mozilla (được biết đến với tên là Spider SpiderMonkey,). Nó dựa trên một kỹ thuật được phát triển tại UC Irvine có tên là cây dấu vết, và xây dựng mã và ý tưởng được chia sẻ với dự án Tamarin Trace. Kết quả cuối cùng là sự gia tăng tốc độ lớn cả về nội dung trang chrome và trang web của trình duyệt.


1
Cảm ơn câu trả lời này, nó thực sự trả lời câu hỏi. Tôi cho rằng nhận xét cuối cùng về việc không có trình biên dịch tĩnh là nguyên nhân gây ra tiếng vang về việc triển khai nào thực sự biên dịch mã và cái nào không. Tất cả những gì tôi quan tâm là tính hợp lệ của tuyên bố "JavaScript là ngôn ngữ được diễn giải", trong đó, các trích dẫn thực hiện và sự thiếu định nghĩa của thông số kỹ thuật, dường như là sai. Không khuyến khích cho đoạn thứ hai của "Hướng dẫn dứt khoát", nhưng tôi đoán tôi sẽ gắn bó với nó.
Matt Esch

@ me 232, tuyên bố này thực sự đúng trước năm 2008. Rhino trước ngày đó nhưng không phải là người phiên dịch chính và rất ít người có lỗi trong "Hướng dẫn dứt khoát" tại thời điểm đó vì đã bỏ qua nó. Tôi chưa đọc cuốn sách này, vì vậy tôi không thể nhận xét về câu nói đó có chất lượng như thế nào.
Mike Samuel

Định nghĩa của "trình biên dịch tĩnh" là gì. Tôi nghĩ rằng định nghĩa có nghĩa là quá trình biên dịch chỉ xảy ra một lần và bạn nhận được một nhóm bit tĩnh (tức là không thay đổi) mà sau đó bạn thực thi. AFAIK đây không phải là cách mà bất kỳ công cụ JavaScript nào hoạt động. Đó là lý do tại sao họ có de-optimizationcác bước. Nói cách khác, JavaScript được biên dịch bởi các công cụ này nhưng nó không được biên dịch tĩnh.
gman

@gman, trình tạo mã byte của Rhino hoạt động theo cách đó.
Mike Samuel

AFAIK không phải vậy. Rhino có thể bao gồm các tệp JavaScript khác phải được biên dịch khi chạy. Đó không phải là biến chứng tĩnh .
gman

20

VM JavaScript JavaScript được sử dụng trong Chrome không bao gồm trình thông dịch. Thay vào đó, nó bao gồm hai trình biên dịch và biên dịch mã khi đang bay. Một trong những trình biên dịch chạy nhanh nhưng tạo ra mã không hiệu quả, cái còn lại là trình biên dịch tối ưu hóa.

Tôi có thể hiểu tại sao một số người sẽ coi đây là "gian lận", vì V8 lấy mã nguồn làm đầu vào mỗi khi mã chạy và người dùng phải cài đặt V8. Nhưng hãy xem xét một trình biên dịch phát ra một tệp thực thi bao gồm một trình thông dịch và mã byte hoàn chỉnh. Sau đó, bạn sẽ có một chương trình độc lập. Nó sẽ không rất hiệu quả.


19

Sự xuất hiện của trình biên dịch JIT cho các ngôn ngữ script đã làm mờ ranh giới giữa biên dịch và giải thích đến một điểm mà câu hỏi không có nghĩa gì nhiều. Có phải nó chỉ giải thích khi động cơ đọc một dòng mã và ngay lập tức thực thi nó? (Các tập lệnh Shell vẫn thường được triển khai theo cách này.) Có phải là diễn giải khi công cụ lấy toàn bộ tệp, ngay lập tức biên dịch nó thành một số mã byte và sau đó diễn giải mã byte? (Công cụ Mozilla giai đoạn đầu hoạt động theo cách này, cũng như CPython.) Có phải nó diễn giải khi công cụ phân tích cú pháp một chức năng tại một thời điểm và JIT biên dịch nó thành mã gốc? Thế còn những công cụ biên dịch toàn bộ tệp thành mã byte, sau đó JIT một chức năng tại một thời điểm khi cần thiết thì sao? (Hầu hết các công cụ script ngày nay hoạt động theo cách này,

Có nhiều sắc thái giữa biên dịch và giải thích.

Tôi nghĩ định nghĩa hữu ích nhất để giải thích là "được cung cấp mã nguồn của chương trình tại thời điểm thực hiện, không có bước trước thời gian riêng biệt". Theo định nghĩa này, tất cả các công cụ JavaScript là thông dịch viên. Nhưng đây chắc chắn không phải là định nghĩa duy nhất có thể có của giải thích.

Nhưng JavaScript có được thiết kế để giải thích không? Theo một cách nào đó, có: nó có một evalhàm cũng như hàm Functiontạo mà bạn có thể cung cấp mã chương trình dưới dạng một chuỗi sẽ được thực thi. Khả năng tự động xây dựng mã chương trình trong thời gian chạy yêu cầu công cụ có khả năng diễn giải mã nguồn. Nhưng điều này không có nghĩa là bạn không thể làm mọi thứ khác trước thời hạn. Ngay cả trong một ngôn ngữ được biên dịch như C ++ và C #, bạn có thể lấy mã nguồn, biên dịch nó trong bộ nhớ sang mã máy mới và sau đó thực thi điều đó. Thậm chí còn có các thư viện cho điều đó: LLVM + Clang trong C ++ và dự án Roslyn trong C #.

Ngoài ra, cơ chế phân phối cho JavaScript là mã nguồn; không có dạng mã byte được công nhận của nó. C # và Java có mã byte chính thức của họ và mọi người đều mong đợi C ++ sẽ được phân phối dưới dạng mã máy. Nhưng đây vẫn không phải là một khía cạnh vốn có nếu ngôn ngữ, chỉ là một kịch bản sử dụng chi phối. Trên thực tế, ActionScript tương đối gần của JavaScript trong Flash trên thực tế được phân phối dưới dạng mã byte (trình biên dịch Flash biên dịch trước tất cả các tập lệnh).


4

Không có sự đồng ý hoàn toàn theo định nghĩa 'giải thích' so với 'được biên dịch'. Trong phân biệt cổ điển, các ngôn ngữ được biên dịch tạo ra một tệp thực thi nhị phân độc lập, trong khi các ngôn ngữ được giải thích yêu cầu thời gian chạy được triển khai để thực thi mã. Máy ảo, mã byte và như vậy làm mờ sự khác biệt.

Nhưng đây là một định nghĩa có thể hữu ích: Ngôn ngữ được diễn giải là ngôn ngữ mà thời gian chạy ngôn ngữ tiêu chuẩn có thể lấy văn bản mã nguồn làm đầu vào và thực thi nó. Theo định nghĩa đó Perl, Python, Ruby, JavaScript và shell script và những thứ tương tự được diễn giải (ngay cả khi chúng sử dụng các bước trung gian như mã byte hoặc thậm chí mã gốc). Java, C #, C, v.v. Và JavaScript theo định nghĩa được diễn giải, ngay cả khi thông số kỹ thuật không sử dụng từ chính xác.


Hmm, tôi không thích đặt Java và C vào cùng một danh mục. Có lẽ một sự khác biệt tốt hơn là các ngôn ngữ được phân phối phổ biến nhất là (A) mã nguồn, (B) mã trung gian hoặc (C) mã máy. Ví dụ: A = javascript, B = Java, C = C.
John Henckel

Gọi một ngôn ngữ hoặc được giải thích hoặc biên dịch là không đúng. Ví dụ theo quy tắc đó, bạn đồng ý rằng C ++ được biên dịch ngôn ngữ phải không? Vậy còn Cling, thì thực thi mã c ++ mà không biên dịch nó. "Và những thứ tương tự được diễn giải (ngay cả khi họ sử dụng các bước trung gian như mã byte hoặc thậm chí mã gốc)" Theo điều này, java cũng được diễn giải, được VM giải thích.
Abhinav Gauniyal
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.