Hướng dẫn line by line execution in javascript - thực thi từng dòng trong javascript

Đầu tiên, bạn đưa ra một giả định không chính xác: JavaScript hiện đại được biên soạn. Các động cơ như V8, Spidermonkey và Nitro Compile JS nguồn vào mã máy gốc của nền tảng máy chủ.

Ngay cả trong các động cơ cũ hơn, JavaScript không được giải thích. Họ chuyển đổi mã nguồn thành mã byte, mà máy ảo của động cơ thực thi.

Đây thực sự là cách mọi thứ trong ngôn ngữ Java và .NET hoạt động: Khi bạn "biên dịch" ứng dụng của mình, bạn thực sự chuyển đổi mã nguồn thành mã byte của nền tảng, mã byte và CIL tương ứng. Sau đó, trong thời gian chạy, một trình biên dịch JIT biên dịch mã byte vào mã máy.

Chỉ các động cơ JS rất cũ và đơn giản thực sự diễn giải mã nguồn JavaScript, bởi vì việc giải thích là rất chậm.

Vậy tổng hợp JS hoạt động như thế nào? Trong giai đoạn đầu tiên, văn bản nguồn được chuyển thành một cây cú pháp trừu tượng (AST), một cấu trúc dữ liệu đại diện cho mã của bạn theo định dạng mà máy móc có thể xử lý. Về mặt khái niệm, điều này giống như cách văn bản HTML được chuyển đổi thành đại diện DOM của nó, đó là những gì mã của bạn thực sự hoạt động.

Để tạo AST, động cơ phải đối phó với đầu vào của các byte thô. Điều này thường được thực hiện bởi một máy phân tích từ vựng. Lexer không thực sự đọc tệp "từng dòng"; Thay vào đó, nó đọc byte-by-byte, sử dụng các quy tắc của cú pháp ngôn ngữ để chuyển đổi văn bản nguồn thành mã thông báo. Lexer sau đó chuyển luồng mã thông báo cho trình phân tích cú pháp, đó là những gì thực sự xây dựng AST. Trình phân tích cú pháp xác minh rằng các mã thông báo tạo thành một chuỗi hợp lệ.

Bây giờ bạn có thể thấy rõ lý do tại sao một lỗi cú pháp ngăn mã của bạn hoạt động. Nếu các ký tự bất ngờ xuất hiện trong văn bản nguồn của bạn, động cơ không thể tạo ra AST hoàn chỉnh và nó không thể chuyển sang giai đoạn tiếp theo.

Khi động cơ có AST:

  • Một trình thông dịch có thể chỉ cần bắt đầu thực hiện các hướng dẫn trực tiếp từ AST. Điều này rất chậm.
  • Việc triển khai JS VM sử dụng AST để tạo mã byte, sau đó bắt đầu thực thi mã byte.
  • Trình biên dịch sử dụng AST để tạo mã máy, CPU thực thi.

Vì vậy, bây giờ bạn có thể thấy rằng tối thiểu, việc thực thi JS xảy ra theo hai giai đoạn.

Tuy nhiên, các giai đoạn thực hiện thực sự không có tác động đến lý do tại sao ví dụ của bạn hoạt động. Nó hoạt động vì các quy tắc xác định cách đánh giá và thực thi các chương trình JavaScript. Các quy tắc có thể dễ dàng được viết theo cách mà ví dụ của bạn sẽ không hoạt động, không có tác động đến cách chính động cơ thực sự diễn giải/biên dịch mã nguồn.

Cụ thể, JavaScript có một tính năng thường được gọi là nâng cao. Để hiểu được nâng cao, bạn phải hiểu sự khác biệt giữa khai báo hàm và biểu thức chức năng.

Đơn giản, một khai báo chức năng là khi bạn khai báo một chức năng mới sẽ được gọi ở nơi khác:

function foo() {

}

Một biểu thức chức năng là khi bạn sử dụng từ khóa function ở bất kỳ nơi nào mong đợi một biểu thức, chẳng hạn như gán biến hoặc trong một đối số:

var foo = function() { };

$.get('/something', function() { /* callback */ });

JavaScript bắt buộc các khai báo chức năng (loại đầu tiên) được gán cho các tên biến ở đầu bối cảnh thực thi, bất kể khai báo ở đâu trong văn bản nguồn (của ngữ cảnh). Bối cảnh thực thi gần như tương đương với phạm vi - theo thuật ngữ đơn giản, mã bên trong một hàm hoặc phần trên cùng của tập lệnh của bạn nếu không bên trong một hàm.regardless of where the declaration appears in source text (of the context). An execution context is roughly equatable to scope – in plain terms, the code inside a function, or the very top of your script if not inside a function.

Điều này có thể dẫn đến hành vi rất tò mò:

var foo = function() { console.log('bar'); };

function foo() { console.log('baz'); }

foo();

Bạn mong đợi điều gì sẽ được đăng nhập vào bảng điều khiển? Nếu bạn chỉ cần đọc mã tuyến tính, bạn có thể nghĩ baz. Tuy nhiên, nó thực sự sẽ đăng nhập bar, bởi vì tuyên bố của foo được nâng lên trên biểu thức gán cho foo.

Vì vậy, để kết luận:

  • Mã nguồn JS không bao giờ là "đọc" từng dòng.
  • Mã nguồn JS thực sự được biên dịch (theo nghĩa thực sự của từ) trong các trình duyệt hiện đại.
  • Động cơ biên dịch mã trong nhiều lần vượt qua.
  • Hành vi là ví dụ của bạn là sản phẩm phụ của các quy tắc của ngôn ngữ JavaScript, chứ không phải cách nó được biên dịch hoặc giải thích.

Gần đây tôi đã thảo luận với một vài Devs Devs về - cách JS phân bổ bộ nhớ và cách một kịch bản được phân tích cú pháp và thực thi. Đây là một trong nhiều chủ đề quan trọng nhất (hầu hết) không bao giờ là một phần trong sự nghiệp học tập của chúng tôi, không ai cần biết để viết một chương trình JS. Nhưng các chủ đề như thế này là rất quan trọng đối với những nhà phát triển tò mò ngoài kia, những người nghiêm túc với mọi thứ. Tôi đã chọn viết về chủ đề này bởi vì tôi thấy nó khá mơ hồ và mọi người có xu hướng so sánh mọi thứ, đặc biệt là những người quen thuộc với các ngôn ngữ lập trình khác như PHP, C ++, Java, v.v. Một thời gian để tiêu hóa một số khía cạnh quan trọng của JS ban đầu, như làm thế nào JavaScript bị chủ đề đơn có thể không chặn và đồng thời?HOW JavaScript being single-threaded can be non-blocking and concurrent?

Bây giờ trước khi chúng ta bắt đầu lặn sâu, hãy làm rõ khái niệm cơ bản và sự khác biệt giữa động cơ JavaScript và môi trường thời gian chạy JavaScript. - Mặt khác, môi trường thời gian chạy JavaScript, vì tên này có trách nhiệm tạo ra một hệ sinh thái với các cơ sở, dịch vụ và hỗ trợ (như mảng, chức năng, thư viện lõi, v.v.) được yêu cầu cho các hướng dẫn thực thi để chạy thành công .
- JavaScript engine is a program that is used to parse a given script and convert it to machine-executable instructions.
- On the other hand JavaScript run-time environment, as the name implies is responsible for creating an ecosystem with facilities, services, and supports (like array, functions, core libraries, etc.) that are required for the executable instructions to run successfully.

Mô hình chức năng

Hầu như tất cả các trình duyệt web đều có một công cụ JavaScript. Những cái phổ biến nhất là V8 trong Google Chrome và Node.js, Spider Monkey of Mozilla, IE, Chakra, v.v. Mặc dù tất cả các nhà cung cấp trình duyệt này đã triển khai JS khác nhau, nhưng dưới mui xe, tất cả đều theo cùng một mô hình cũ.

Hình: 1

Gọi ngăn xếp, API web, vòng lặp sự kiện, hàng đợi nhiệm vụ, hàng đợi kết xuất, v.v ... Tất cả chúng ta đều nghe thấy các thuật ngữ buzz này trong công việc hàng ngày của chúng ta. Nói chung, tất cả đều làm việc cùng nhau để giải thích và thực hiện các khối mã đồng bộ và không đồng bộ mà chúng ta viết mỗi ngày. Chúng ta hãy nhìn sâu vào mô hình và cố gắng hiểu những gì họ làm và quan trọng nhất là cách thức.

Nhiệm vụ đồng bộ

Có nghĩa là gì? Giả sử chúng tôi có 2 dòng mã dòng 1 theo sau là Line-2. Đồng bộ có nghĩa là Line-2 không thể bắt đầu chạy cho đến khi Line-1 thực hiện xong.Say we have 2 lines of codes Line-1 followed by Line-2. Synchronous means Line-2 can not start running until the Line-1 has finished executing.

JavaScript là một luồng đơn, có nghĩa là chỉ có một câu lệnh được thực thi tại một thời điểm. Khi JS Engine xử lý từng dòng tập lệnh của chúng tôi, nó sử dụng ngăn xếp gọi đơn này để theo dõi các mã được cho là chạy theo thứ tự tương ứng của chúng. Giống như những gì một ngăn xếp làm, một cấu trúc dữ liệu ghi lại các dòng hướng dẫn thực thi và thực hiện chúng theo cách LIFO. Vì vậy, hãy nói rằng nếu động cơ bước vào function foo(){, nó sẽ đẩy foo () vào ngăn xếp và khi việc thực hiện foo () ________ 9 đã vượt qua foo () được bật ra khỏi ngăn chặn., which means only one statement is executed at a time. As the JS engine processes our script line by line, it uses this single Call-Stack to keep track of codes that are supposed to run in their respective order. Like what a stack does, a data structure that records lines of executable instructions and executes them in a LIFO manner. So say if the engine steps into a function foo(){ it PUSH-es foo() into the stack and when the execution of foo()return; } is over foo() is POP-ped out of the call-stack.

Hình: 2.1 Thực hiện đồng bộ các tác vụ Ví dụ 1

Bài tập 1: Vì vậy, từ sơ đồ trên cho thấy cách thực hiện theo dòng điển hình xảy ra. Khi tập lệnh của ba câu lệnh console.log () được ném vào JS - Bước 1:

var foo = function() { };

$.get('/something', function() { /* callback */ });
0is được đẩy vào ngăn xếp cuộc gọi và được thực thi, sau khi thực hiện với thực thi, thì nó được bật ra khỏi ngăn xếp. Bây giờ ngăn xếp trống và sẵn sàng cho bất kỳ hướng dẫn tiếp theo nào được thực thi. So from the above diagram shows how a typical line by line execution happens. When the script of three console.log() statements is thrown at JS —
Step 1: The
var foo = function() { };

$.get('/something', function() { /* callback */ });
0is pushed into the call stack and executed, once done with execution, it is then popped out of the stack. Now the stack is empty and ready for any next instruction to be executed.
Step 2:
var foo = function() { };

$.get('/something', function() { /* callback */ });
1is pushed and the same thing repeats until - Step 3: is executed and there is nothing left to push and execute.

Hãy tham gia vào bài tập tiếp theo của chúng tôi:

Hình: 2.2 Thực hiện đồng bộ các nhiệm vụ Ví dụ 2

Bài tập 2: Vậy những gì đang xảy ra ở đây như sau: So what's happening here is as follows:

Bước 1: Stack cuộc gọi được thúc đẩy với câu lệnh thực thi đầu tiên của tập lệnh của chúng tôi, cuộc gọi chức năng

var foo = function() { };

$.get('/something', function() { /* callback */ });
2. Trong khi thực hiện thông qua phạm vi của hàm
var foo = function() { };

$.get('/something', function() { /* callback */ });
2 Động cơ của chúng tôi gặp một chức năng khác, hãy gọi
var foo = function() { };

$.get('/something', function() { /* callback */ });
4
Call stack is pushed with the first executable statement of our script the
var foo = function() { };

$.get('/something', function() { /* callback */ });
2 function call. While executing through the scope of the function
var foo = function() { };

$.get('/something', function() { /* callback */ });
2 our engine encounters another function call
var foo = function() { };

$.get('/something', function() { /* callback */ });
4

Bước 2: Do đó, chức năng gọi

var foo = function() { };

$.get('/something', function() { /* callback */ });
4 được đẩy vào ngăn xếp cuộc gọi và động cơ bắt đầu thực thi ________ 14function cơ thể (Lưu ý: Hàm
var foo = function() { };

$.get('/something', function() { /* callback */ });
2is vẫn chưa hoàn thành), một lần nữa, có một chức năng khác gọi
var foo = function() { };

$.get('/something', function() { /* callback */ });
8 bên trong
var foo = function() { };

$.get('/something', function() { /* callback */ });
9
Hence the function call
var foo = function() { };

$.get('/something', function() { /* callback */ });
4 is pushed into the call stack and the engine starts executing
var foo = function() { };

$.get('/something', function() { /* callback */ });
4function’s body (Note: The function
var foo = function() { };

$.get('/something', function() { /* callback */ });
2is still not finished), again, there’s another function call
var foo = function() { };

$.get('/something', function() { /* callback */ });
8 inside
var foo = function() { };

$.get('/something', function() { /* callback */ });
9 body.

Bước 3: Tương tự như vậy, chức năng gọi

var foo = function() { };

$.get('/something', function() { /* callback */ });
8 được đẩy vào ngăn xếp cuộc gọi và động cơ bắt đầu xử lý định nghĩa chức năng
var foo = function() { };

$.get('/something', function() { /* callback */ });
8. Trong khi các chức năng
var foo = function() { };

$.get('/something', function() { /* callback */ });
4 và
var foo = function() { };

$.get('/something', function() { /* callback */ });
2Still sống trong ngăn xếp chờ đến lượt của họ (người kế nhiệm hoàn thành việc thực hiện của họ) tương ứng.
Likewise the function call
var foo = function() { };

$.get('/something', function() { /* callback */ });
8 is pushed into the call stack and the engine starts processing
var foo = function() { };

$.get('/something', function() { /* callback */ });
8 function definition. While the functions
var foo = function() { };

$.get('/something', function() { /* callback */ });
4 and
var foo = function() { };

$.get('/something', function() { /* callback */ });
2still living in the stack waiting for their turn (successor to finish their execution) respectively.

Bước 4: Vì vậy, khi động cơ gặp phải câu lệnh

var foo = function() { console.log('bar'); };

function foo() { console.log('baz'); }

foo();
4 trong định nghĩa hàm của
var foo = function() { };

$.get('/something', function() { /* callback */ });
8, thì đó là sự kết thúc của
var foo = function() { };

$.get('/something', function() { /* callback */ });
8. Do đó
var foo = function() { };

$.get('/something', function() { /* callback */ });
8 được bật ra khỏi ngăn xếp cuộc gọi vì nó đã hoàn thành thực thi. Tại thời điểm này, động cơ đã trở lại trong việc thực hiện các dịch vụ của
var foo = function() { };

$.get('/something', function() { /* callback */ });
4.
So when the engine encounters a
var foo = function() { console.log('bar'); };

function foo() { console.log('baz'); }

foo();
4 statement within the function definition of
var foo = function() { };

$.get('/something', function() { /* callback */ });
8 , well that’s the end of
var foo = function() { };

$.get('/something', function() { /* callback */ });
8 . Hence
var foo = function() { };

$.get('/something', function() { /* callback */ });
8 is popped out of the call stack as it has finished execution. At this point, the engine is back at executing
var foo = function() { };

$.get('/something', function() { /* callback */ });
4 ‘s offerings.

Bước 5: Cũng như động cơ gặp phải câu lệnh

var foo = function() { console.log('bar'); };

function foo() { console.log('baz'); }

foo();
4, hàm
var foo = function() { };

$.get('/something', function() { /* callback */ });
4 được bật ra và động cơ bắt đầu thực thi
var foo = function() { };

$.get('/something', function() { /* callback */ });
2. Bây giờ, không có tuyên bố hoàn trả nào trong phạm vi của
var foo = function() { };

$.get('/something', function() { /* callback */ });
2 để động cơ thực hiện cơ thể cho đến khi kết thúc phạm vi và bật
var foo = function() { };

$.get('/something', function() { /* callback */ });
2 ra khỏi ngăn xếp ở bước 6.
Well as the engine encounters a
var foo = function() { console.log('bar'); };

function foo() { console.log('baz'); }

foo();
4 statement, the function
var foo = function() { };

$.get('/something', function() { /* callback */ });
4 is popped out and the engine starts executing
var foo = function() { };

$.get('/something', function() { /* callback */ });
2 . Now there’s no return statement within the
var foo = function() { };

$.get('/something', function() { /* callback */ });
2 ‘s scope so the engine executes its body until the end of scope and pops
var foo = function() { };

$.get('/something', function() { /* callback */ });
2 out of the stack at Step 6.

Đó là cách mà một kịch bản của các tác vụ đồng bộ được xử lý bởi trình duyệt của chúng tôi mà không liên quan đến bất cứ điều gì khác ngoài ngăn xếp cuộc gọi huyền thoại của Hồi giáo. Nhưng mọi thứ trở nên phức tạp một chút khi động cơ JS gặp một nhiệm vụ không đồng bộ.

Nhiệm vụ không đồng bộ

Có nghĩa là gì có nghĩa là gì? Không giống như đồng bộ, không đồng bộ là một hành vi. Giả sử nếu chúng ta có hai dòng mã dòng 1 theo sau là Line-2. Line-1 là một hướng dẫn tốn thời gian. Vì vậy, Line-1 bắt đầu thực hiện hướng dẫn của nó trong nền (như quy trình daemon), cho phép Line-2 bắt đầu thực thi mà không phải chờ Line-1 kết thúc.Unlike synchronous, asynchronous is a behavior. Say if we have two lines of code Line-1 followed by Line-2. Line-1 is a time-consuming instruction. So Line-1 starts executing its instruction in the background (like a daemon process), allowing Line-2 to start executing without having to wait for Line-1 to finish.

Chúng ta cần hành vi này khi mọi thứ chậm. Thực thi đồng bộ mã có vẻ đơn giản nhưng có thể chậm. Các nhiệm vụ như xử lý hình ảnh có thể chậm, các hoạt động tệp có thể thực sự chậm, việc yêu cầu mạng và chờ phản hồi chắc chắn là chậm, tạo ra các tính toán lớn như hơn 100 triệu lần lặp lại cho vòng lặp có phần chậm. Vì vậy, những điều chậm chạp như vậy trong Stack Stack dẫn đến việc chặn chặn. Khi ngăn xếp cuộc gọi bị chặn, trình duyệt sẽ ngăn người dùng ngắt và các câu lệnh mã khác thực thi cho đến khi câu lệnh chặn được thực thi và ngăn xếp cuộc gọi được giải phóng. Do đó, các cuộc gọi lại không đồng bộ được sử dụng để xử lý các tình huống như vậy.slow. Tasks like image processing can be slow, file operations can be really slow, making a network request and waiting for response is definitely slow, making huge calculations like over a 100 million for-loop iteration is somewhat slow. So such slow things in Call stack results in “Blocking”. When the call stack is blocked, the browser prevents the user’s interrupts and other code statements from executing until the blocking statement is executed and the call stack is freed. Hence Asynchronous callbacks are used to handle such situations.

Ví dụ: Vâng, hàm function4 có lẽ là cách đơn giản nhất và dễ nhất để chứng minh hành vi không đồng bộ.: Well the function function4 is probably the simplest and easiest way to demonstrate asynchronous behavior.

Hình: 3.1 Ví dụ về SetTimeout

Bài tập 3: Nếu chúng ta theo dõi ngăn xếp cuộc gọi, chúng ta có thể thấy: Ở bước 1: Như thường lệ function5 bị đẩy vào ngăn xếp trước và được thực hiện sau đó xuất hiện khi thực hiện. không thể được thực thi (hoặc được đẩy vào ngăn xếp) ngay lập tức vì nó có nghĩa là thực thi trong một thời gian trong tương lai (nghĩa là sau tối thiểu 2 giây). Vì vậy, nó biến mất ngay bây giờ (sẽ giải thích sau đó nơi nó biến mất) .step 3: Dòng tiếp theo tự nhiên function8 được đẩy vào ngăn xếp, được thực thi và được bật ra ngay lập tức. Đột nhiên function9 được tìm thấy bị đẩy vào ngăn xếp sau 2 giây vì function4 đã hết thời gian. Sau đó, nó được thực hiện và sau khi hoàn thành được bật ra khỏi ngăn xếp ở bước 6: Stack lại trống. If we trace the call-stack we can see:
at Step 1: As usual function5 gets pushed into the stack first and is executed then popped out when done.
Step 2: function4 gets pushed into the stack, but Note- function7 cannot be executed (or pushed to the stack) immediately because it is meant to execute in some future time (i.e. after a minimum of 2 seconds). So it disappears for now (will explain later where it disappears to).
Step 3: Naturally next line function8 is pushed into the stack, gets executed, and is popped out immediately.
Step 4: Call stack is empty and waiting.
Step 5: Suddenly function9 is found pushed into the stack after 2 seconds as function4 has timed out. It is then executed and once done is popped out of the Stack at Step 6: Stack is empty again.

Do đó, nó chứng minh, mặc dù JavaScript là một luồng, chúng ta có thể đạt được sự đồng thời thông qua việc xử lý không đồng bộ các nhiệm vụ.

Bây giờ chúng ta còn lại ba câu hỏi quan trọng: Câu 1. Điều gì đã xảy ra với ____34? Câu hỏi 2. Nó đã trở lại từ đâu? Và câu hỏi 3. Nó đã xảy ra như thế nào?
Question 1. WHAT happened to thefunction4 ?
Question 2. From WHERE did it came back? And
Question 3. HOW did it happen?

Vì vậy, đây là nơi vòng lặp sự kiện, hàng đợi gọi lại và API Web (trong trình duyệt) bắt đầu. Hãy giới thiệu từng phần trên và trả lời 3 câu hỏi trên thông qua sơ đồ tiếp theo của chúng tôi.Event Loop, Callback Queue, and Web APIs (in browser) kicks in. Let's introduce each of the above pieces and answer the above 3 questions through our next diagram.

Hình: 3.2 Trình diễn cuối cùng của toàn bộ mô hình

Bài tập 4: Hãy nhảy ngay vào Let's jump right into

Bước 2: Tại thời điểm này baz2 bị đẩy vào ngăn xếp cuộc gọi. Như chúng ta có thể thấy nó có hai thành phần A baz3 và baz4. Bây giờ function4 không phải là một phần của bất kỳ động cơ JavaScript nào, trên thực tế, nó có một API web được bao gồm trong môi trường trình duyệt như một tính năng bổ sung. At this point baz2 gets pushed into the call stack. As we can see it has two components a baz3 and a baz4 . Now function4 is NOT a part of any JavaScript engine, it’s in fact, a Web API included in the browser environment as an extra feature.

Bước 3: Vì vậy, API Web Trình duyệt chịu trách nhiệm của baz3 được cung cấp và kích hoạt bộ đếm thời gian của 2000 ms để lại tuyên bố function4 đã hoàn thành công việc của mình, vì vậy nó đã bật ra khỏi ngăn xếp. [Câu 1 được trả lời]So the browser Web API takes the responsibility of the baz3 provided and fires up the timer of 2000 ms leaving behind function4 statement which has done its job, so it popped out of the stack. [ Question 1 is answered]

Bước 4: Dòng tiếp theo trong tập lệnh của chúng tôi baz8 được đẩy vào ngăn xếp và bật ra sau khi thực hiện. The next line in our script baz8 is pushed into the stack and popped out after its execution.

Bước 5: Bây giờ chúng tôi có một baz9in Webapis sẽ được kích hoạt sau 2000 ms. Nhưng Webapis trực tiếp không thể đẩy mọi thứ ngẫu nhiên vào ngăn xếp cuộc gọi, bởi vì nó có thể tạo ra một sự gián đoạn cho một số mã khác được thực thi bởi công cụ JavaScript tại thời điểm đó. Vì vậy, thay vào đó, baz3 được chèn vào hàng đợi/hàng đợi gọi lại sau khi hẹn giờ của bar1is. Webapi hiện đang trống và được giải phóng Now we have a baz9in the WebAPIs which is going to get triggered after 2000 ms. But WebAPIs directly can not PUSH things randomly into the call-stack, because it might create an interrupt to some other code being executed by the JavaScript engine at that moment. So instead the baz3 is inserted into the Callback Queue/Task Queue after the timer of bar1is over. WebAPI is now empty and freed

Bước 6: Vòng lặp sự kiện-Nó chịu trách nhiệm lấy phần tử đầu tiên từ hàng đợi gọi lại/nhiệm vụ và đẩy nó vào ngăn xếp cuộc gọi chỉ khi ngăn xếp hoặc miễn phí, vì vậy tại thời điểm này của phương trình của chúng tôi, ngăn xếp cuộc gọi trống rỗng. Event Loop — it is responsible for taking out the first element from the Callback/Task Queue and PUSH it into the Call-Stack only when the stack is empty or free, so at this point of our equation, the Call-Stack is empty.

Bước 7: Vì vậy, baz3 được đẩy vào ngăn xếp cuộc gọi (vì nó miễn phí và trống rỗng) từ Callback/Taskqueue bởi vòng lặp sự kiện và baz3 được thực thi. [Câu 2 được trả lời] So baz3 is pushed into the Call-Stack (as it was free and empty) from the Callback/Task queue by the Event Loop, and baz3 is executed. [Question 2 is answered]

Bước 8: Vì vậy, một tuyên bố thực thi khác function7 được tìm thấy bên trong phạm vi của baz3, do đó function7 được đẩy vào ngăn chặn cuộc gọiSo another executable statement function7 is found inside the baz3 ‘s scope, therefore function7 is pushed into the Call-Stack

Bước 9: Sau khi function7 được thực thi, sau đó nó được bật ra khỏi ngăn xếp gọi và động cơ JavaScript quay lại để hoàn thành việc thực hiện cơ thể còn lại của baz3. Mà khi được thực hiện, baz3 được bật ra khỏi đoạn gọi. Phần cuối của câu chuyện [trả lời các cách thức của người Viking, tức là câu hỏi 3]. Once function7 is executed, it is then popped out of the Call-Stack, and the JavaScript engine comes back to finish executing the baz3 ‘s remaining body. Which when done, baz3 is popped out of the Call-Stack. The End of the story [Answers the “HOW”, i.e Question 3].

Chà, đây là một cuộc biểu tình rất dễ dàng, nhưng mọi thứ trở nên lộn xộn và phức tạp trong các tình huống như khi có nhiều lần được xếp hàng - kết quả khác nhau so với những gì mà thường được mong đợi (đây là một chủ đề thú vị khác để thảo luận). Tôi không biết làm thế nào chính xác tôi có thể chứng minh chủ đề này nhưng có rất nhiều thứ có thể được xây dựng hoặc giải thích tốt hơn, nhưng tôi đã vội vàng và nó đã quá dài. Hy vọng nó sẽ giúp ai đó.

Thực thi trong JavaScript là gì?

Bối cảnh thực thi chứa mã hiện đang chạy và mọi thứ hỗ trợ thực thi. Trong thời gian chạy ngữ cảnh thực thi, mã cụ thể được phân tích cú pháp, các biến và hàm được lưu trữ trong bộ nhớ, mã byte có thể thực thi được tạo và mã được thực thi.. During the Execution Context run-time, the specific code gets parsed by a parser, the variables and functions are stored in memory, executable byte-code gets generated, and the code gets executed.

JavaScript có được thực hiện tuần tự không?

39.1.2 JavaScript thực thi các nhiệm vụ theo tuần tự trong một quy trình.Vòng lặp này còn được gọi là vòng lặp sự kiện vì các sự kiện, chẳng hạn như nhấp chuột, thêm các tác vụ vào hàng đợi.JavaScript executes tasks sequentially in a single process. This loop is also called the event loop because events, such as clicking a mouse, add tasks to the queue.

JavaScript là đồng bộ hay không đồng bộ?

JavaScript là một ngôn ngữ lập trình đồng thời, không chặn, không đồng bộ, không đồng thời với rất nhiều sự linh hoạt.asynchronous, concurrent programming language with lots of flexibility.

Làm thế nào để JavaScript được thực thi?

Mã nguồn được chuyển qua một chương trình gọi là trình biên dịch, chuyển nó thành mã byte mà máy hiểu và có thể thực thi.Ngược lại, JavaScript không có bước tổng hợp.Thay vào đó, một trình thông dịch trong trình duyệt đọc qua mã JavaScript, diễn giải từng dòng và chạy nó.an interpreter in the browser reads over the JavaScript code, interprets each line, and runs it.