Hướng dẫn javascript runtime là gì

JavaScript Runtime Environment là gì?

Một khái niệm, thành phần khá quan trọng trong lập trình JavaScript đó là JavaScript Runtime Enviroment.

JavaScript Runtime Environment là gì?

Trước tiên, mình giải thích lại cách hoạt động của JavaScript. JavaScript khác với các ngôn ngữ biên dịch như C/C++. JavaScript chạy trong một container – container này chính là một phần mềm thực hiện đọc code JavaScript và thực thi nó.

Phần đọc code và chuyển thành các đoạn mã để container có thể hiểu chính là nhiệm vụ của JavaScript Engine.

Phần thực thi các đoạn mã đó lại thuộc về JavaScript Runtime Enviroment. JavaScript Runtime Enviroment cung cấp các đối tượng, môi trường để JavaScript giao tiếp với máy tính.

Ví dụ Chrome Browser và Node.js đều sử dụng chung JavaScript Engine là V8. Tuy nhiên JavaScript Runtime Enviroment trong 2 trường hợp này lại khác nhau:

  • Chrome Browser sử dụng các đối tượng như window, DOM object hay các method như AJAX… để giao tiếp với network và hiển thị.
  • Node.js lại cung cấp các thư viện cho phép truy cập trực tiếp các file trên máy tính, truy cập database, tiến trình (Chrome Browser không làm được các việc này)

Ví dụ: dưới đây chính là JavaScript Runtime Enviroment hoạt động trên Chrome Browser:

Hướng dẫn javascript runtime là gì

Okay, Done!

References:

https://medium.com/…/the-javascript-runtime-environment

Bài viết được sự cho phép của tác giả Trần Hữu Cương

JavaScript Engine là một chương trình máy tính thực thi các đoạn code JavaScript (JS).

JavaScript đọc các đoạn mã JavaScript rồi chuyển nó sang mã máy để máy tính (hoặc phần mềm máy tính như trình duyệt web, server node.js…) có thể hiểu và chạy được.

Hướng dẫn javascript runtime là gì

Hướng dẫn javascript runtime là gì

Nếu bạn đã lập trình với Java hay C/C++ thì có thể hiểu JavaScript tương đương với JDK trong Java hay trình Compiler C/C++ trong lập trình C/C++.

Các bản JavaScript Engine phổ biến

Có nhiều bản JavaScript Engine được phát triển bởi các các vendor (nhà cung cấp) khác nhau. Một số JavaScript Engine phổ biến như:

  • SpiderMonkey  – Phiên bản Javascript engine đầu tiên, được dùng trên trình duyệt web đầu tiên trên thế giới – Netscape Navigator, hiện tại đang được sử dụng trên Firefox, viết bằng C và C++.
  • Chakra – Là một Javascript engine cũng khá lâu đời, ban đầu được sử dụng trên Internet Explorer và biên dịch JScript, nay được dùng cho Microsoft Edge, viết bằng C++.
  • Rhino – Một Engine viết hoàn toàn bằng Java, cũng có lịch sử phát triển lâu đời từ Netscape Navigator, hiện tại được phát triển bởi Mozilla Foundation.
  • Google V8 – Được phát triển bới Google (Chromium Project).

Ngoài các JS Engine trên, còn rất nhiều JavaScript Engine khác như Carakan, JavaScriptCore, Tamarin, Nashorn…

JavaScript dùng ở đâu?

Đầu tiên, các JavaScript Engine chủ yếu được phát triển và cài đặt cho các trình duyệt web (web browser). Ví dụ Chrome V8 dùng cho Google Chrome, SpiderMonkey dùng cho trình duyệt FireFox… Tức là chỉ dùng cho client.

Sau này, các JavaScript Engine được áp dụng để lập trình server với Node.js runtime system.

Một số phần mềm cũng áp dụng JavaScript Engine để lập trình phần mềm bằng JavaScript như MongoDB…

Bài viết gốc được đăng tải tại codecute.com

Có thể bạn quan tâm:

  • Hiểu hơn về cách hoạt động của JavaScript Engine
  • Software engineer phát triển bản thân như thế nào?
  • Cách thức hoạt động của JavaScript: V8 engine và 5 mẹo tối ưu hóa

Xem thêm tìm việc javascript lương cao hấp dẫn trên TopDev

Nguồn: https://blog.sessionstack.com/how-does-javascript-actually-work-part-1-b0bacc073cf

Notes: Bài này là bài dịch từ blog khác, mình sẽ loại bỏ phần quảng cáo không liên quan để các bạn tập trung vào kiến thức được chia sẻ cụ thể trong bài này. Nếu muốn đọc sâu hơn và kỹ hơn thì các bạn nên đọc bài gốc. Cảm ơn ^^!

JavaScript đang càng ngày càng phổ biến, các đội ngũ lập trình viên đang tận dụng hầu hết hiệu quả của nó để phát triển và giải quyết các bài toán hiện nay trong các ứng dụng của họ như Front-end, Back-end, hybrid apps, embedded devices và nhiều hơn thế.

Blog này cũng là bài đầu tiên trong series tìm hiểu sâu về JavaScript và cách hoạt động thực tế của nó: chúng tôi tin rằng việc hiểu sâu hơn việc các code blocks trong javaScript được xây dựng như thế nào, và cách chúng hoạt động với nhau ra sao sẽ giúp các lập trình viên tối ưu hoá code của họ nhiều hơn, làm cho các ứng dụng chạy tốt, nhanh và hiệu quả hơn.

Trong biểu đồ dưới đây thể hiện số liệu thống kê trên GitHub. JavaScript hiện tại đang đứng đầu số các repo và số lượt push lên Git. Rõ ràng là nó không bị tụt lại phía sau nhiều như các ngôn ngữ khác.

Hướng dẫn javascript runtime là gì

Việc các dựng án hiện tại đang phụ thuộc vào JavaScript ngày càng nhiều, bắt buộc các lập trình viên phải hiểu nhiều và hiểu sâu hơn về bản chất vấn đề với JavaScript để có thể sử dụng nó tốt hơn và tạo ra những ứng dụng chất lượng và tuyệt vời hơn.

Hoá ra là hiện tại có rất nhiều các lập trình viên sử dụng javaScript hằng ngày như cơm bữa, nhưng thực tế lại không hiểu rõ câu chuyện vận hành thực sự đằng sau đó là gì. (thí dụ tui ^^)

Khái Quát

Hầu như tất cả mọi người đã nghe về khái niệm V8 Engine (đọc thêm ở đây) và JavaScript thực chất là single-threaded (đơn luồng) hoặc về việc javascript sử dụng các Callback Queue

Trong bài này chúng ta sẽ đi qua hết chi tiết các khái niệm trên và tìm hiểu sâu về cách hoạt động của chúng. Khi hiểu được bản chất vấn đề bạn đương nhiên có thể viết được một ứng dụng tốt hơn, non-blockings và tận dụng đúng và tốt nhất các APIs được cung cấp.

Nếu bạn là một beginner JavaScript thì qua bài này bạn có thể hiểu hơn tại sao JavaScript được coi là một ngôn ngữ khá "kỳ cục" so với hầu hết các ngôn ngữ khác.

Còn nếu bạn đã có kinh nghiệm với JavaScript rồi thì hy vọng bài này sẽ cung cấp cho bạn vài khái niệm mới về cách mà JavaScript Runtime hoạt động. Thứ mà bạn đang làm việc với nó hằng ngày.

The JavaScript Engine

Một trong những Engine phổ biến nhất của javaScript là Google’s V8 engine. Ví dụ nó được dùng trong trình duyệt Chrome và Nodejs. Đây là hình ảnh cụ thể và đơn giản nhất mô tả V8 engine.

Hướng dẫn javascript runtime là gì

Engine này bao gồm 2 components chính:

  • Memory Heap -- Các tác vụ phân bổ vùng nhớ sẽ thực hiện ở đây.
  • Call Stack -- Nơi mà các Stack frames trong code của bạn sẽ được thực thi.

The Runtime

Trong thực tế hiện này có một số APIs trên trình duyệt mà chúng ta vẫn đang sử dụng hằng ngày (vd: “setTimeout”). Tuy nhiên những APIs này lại không được cung cấp bởi Engine.

Vậy những APIs này từ đâu mà có?

Hoá ra thực tế lại có chút phức tạp hơn chúng ta nghỉ.

Hướng dẫn javascript runtime là gì

Vậy ở đây chúng ta có Engine, nhưng không chỉ có thế. Chúng ta còn có thêm một thứ gọi là Web APIs. Những APIs này được cung cấp bởi chính browser mà chúng ta đang sử dụng. Các APIs đó bao gồm DOM, AJAX setTimeout,...

Và tiếp đó còn có các event loop (sự kiện vòng lặp) thông dụng và callback queue.

The Call Stack

JavaScript là ngôn ngữ single-threaded (đơn luồng). Có nghĩa là nó chỉ có một call stack đơn lẻ. Cho nên nó chỉ thực hiện duy nhất mỗi 1 tác vụ trong một lần thực thi.

Call Stack là một cấu trúc dữ liệu ghi lại cụ thể nơi mà đoạn code của chúng ta được thực thi trong chương trình. Khi bạn bắt đầu một function, function đó sẽ được đẩy vào vùng chứa đầu tiên của stack. Rồi khi function đó kết thúc thì nó sẽ được remove ra khỏi stack. Đó là toàn bộ những gì stack có thể làm cho bạn.

Hãy xem một ví dụ sau đây. Theo dõi đoạn code sau:

function multiply(x, y) {
    return x * y;
}
function printSquare(x) {
    var s = multiply(x, x);
    console.log(s);
}
printSquare(5);

Khi Engine bắt đầu thực thi đoạn code này thì Call Stack lúc đó sẽ rỗng. Các bước thực thi tiếp theo trong Call Stack sẽ trông như thế này:

Hướng dẫn javascript runtime là gì

Từng lần ghi lại trong stack sẽ được gọi là Stack Frame.

Còn đây mô tả chính xác các stack trace (vết tích của stack) được tạo ra trong call stack khi có một exception (ngoại lệ/error) văng ra --- hay còn gọi là trạng thái của Call Stack khi xảy ra exception. Theo dõi đoạn code sau đây.

function foo() {
    throw new Error('SessionStack will help you resolve crashes :)');
}
function bar() {
    foo();
}
function start() {
    bar();
}
start();

Nếu mình thực thi đoạn code này trên console của Chrome (giả sử đoạn code này thuộc một file gọi là foo.js). Lúc đó stack trace sẽ xuất ra như thế này:

Hướng dẫn javascript runtime là gì

“Blowing the stack” --- (hiểu nôm na là tràn vùng chứa) --- Vấn đề này sẽ xảy ra khi stack của bạn vượt quá Call Stack size và thực tế là nó rất hay xảy ra. Đặt biệt là khi bạn xài các hàm đệ quy mà ko kiểm soát kỹ. Hãy nhìn đoạn code dưới đây.

function foo() {
    foo();
}
foo();

Khi engine thực thi đoạn code trên. Nó sẽ bắt đầu gọi hàm "foo". Tuy nhiên function foo là một hàm đệ quy, nó tự gọi chính nó mà không hề có bất cứ điều kiện dừng nào. Chính vì vậy cứ mỗi lần function foo được gọi, thì chính nó sẽ được add liên tục vào Call Stack mà không thể dừng lại. Hình dưới đây sẽ minh hoạ rõ hơn:

Hướng dẫn javascript runtime là gì

Tuy nhiên một khi số lượng các hàm "foo" được gọi vượt quá size thực tế của Call Stack thì lúc đó browser sẽ thực thi một hành động trả ra lỗi giống như hình dưới đây:

Hướng dẫn javascript runtime là gì

Việc chạy code đơn luồng dường như dễ dàng hơn khi bạn không cần phải đối mặt với những vấn đề phát sinh trong môi trường đa luồng (multi-threaded) --- thí dụ như là deadlocks

Tuy nhiên việc chạy đơn luồng cũng bị hạn chế. Khi mà JavaScript chỉ có một Call Stack đơn lẻ để thực hiện các tác vụ, và phải chờ đợi xong tác vụ này mới tới tác vụ khác. Vậy điều gì xảy ra khi mọi thứ đều trở nên chậm chạp?

Concurrency & the Event Loop

Nếu bạn có một function được gọi trong Call Stack mà function đó lại mất tới một khoản thời gian rất lâu để thực thi xong, lúc đó đó sẽ phải làm thế nào? Tưởng tượng bạn có một số tác vụ muốn chuyển đổi các images code bằng JavaScript và chạy trên trình duyệt.

Bạn có lẽ hỏi --- Thì chuyện này có gì đâu mà lại vấn đề chứ? Vấn đề ở đây là khi mà Call Stack đang thực hiện nhiệm vụ của nó thì browser sẽ không thể làm gì khác được -- nó sẽ bị blocked. Nghĩa là lúc đó browser sẽ không thể render (biên dịch), không chạy các code nào khác. Nó đơn giản là bị kẹt lại một chỗ. Điều này sẽ làm cho app của bạn trở nên chậm chạp, không đẹp và thân thiện với người dùng.

Vấn đề không chỉ dừng ở đó. Một khi mà browser phải thực hiện quá nhiều tác vụ trong Call Stask, nó sẽ bị đứng và người dùng không thể tương tác với browser trong một khoảng thời gian khá lâu. Và rồi lúc đó đa số các trình duyệt sẽ hiện lên một thông báo lỗi và hỏi người dùng muốn tắt trình duyệt hay tiếp tục chờ.

Hướng dẫn javascript runtime là gì

Đây chắc hẳn không phải là một trải nghiệm người dùng tốt nhỉ?

Rồi bây giờ làm sao để thực thi những đoạn code nặng nề mà không làm chậm hoặc đứng trình duyệt? Giải pháp cho tất cả chính là asynchronous callbacks (các callbacks bất đồng bộ).

Điều này sẽ được trình bày chi tiết và rõ ràng hơn trong Part 2 series “How JavaScript actually works”. "Bên trong engine V8 + 5 tips làm code của bạn tốt hơn"