UnderstandJavaScript - Function Invocation And The Execution Stack
Trong nhưng bài trước mình có nói về Global Execution Context , làm thế nào để nó tạo (Create Phase) và thực thi (Execution) và mình cũng đã đề cập rằng các hàm (function) cũng liên quan đến điều này hôm nay mình sẽ nói về Function Invocation và The Execution Stack khái niệm này sẽ là nền tảng cho rất nhiều các khái niệm nâng cao khác.
Invocation :
Điều này có nghĩa là chúng ta muốn invoked , apply hay calling một hàm , trong javascript chúng ta làm điều đó bằng cách sử dụng dấu ngoặc đơn..bạn viết tên một hàm và đặt dấu ngoặc đơn sau nó thế là bạn đã nói với công cụ JavaScipr để chạy nó.Bây giờ chúng ta hãy nói về những gì xảy ra khi bạn gọi một hàm trong JavaScript
Cùng đến một ví dụ
- function b trống
- function a gọi function b bên trong
- Cuối cùng mình invoke function a
=> Đây là ví dụ rất đơn giản những nó giúp chúng ta hiểu được thực sự những gì đang xảy ra bên trong javascript.
- Khi chúng ta chạy chương trình bên trên điều gì đang thực sự diễn ra ?
+ Trước tiên cái gì được tạo ra ?
=> Như mình đã nói ở các bài trường đó là Global Execution Context(created and code is executed)
Syntax Parser sẽ phân tích mã và sau đó trình biên dịch sẽ dịch mã của bạn và nói rằng với JSE rằng "Hey tôi cần tạo ra một Global Execution Context .
+ Trong giai đoạn đầu (Creation Phase) tạo ra Global Execution Context thì JSE sẽ tạo ra biến This , Global Object và Outer Environment , sau đó JSE sẽ tạo ra một không gian trong bộ nhớ để lưu trữ các hàm và các biến được khai báo để dùng trong giai đoạn Code Execution .
+ Trong giai đoạn Code Execution , JSE thực thi chương trình theo từng dòng
Vì vậy b và a sẽ nằm trong bộ nhớ từ đó mã sẽ được thực thi theo từng dòng..nhưng khi nó chạy đến dòng số 7 và nó hiểu được rằng mình muốn chạy hàm a và đây sẽ là nhưng điều xảy ra tiếp theo.
+ Trong giai đoạn đầu (Creation Phase) tạo ra Global Execution Context thì JSE sẽ tạo ra biến This , Global Object và Outer Environment , sau đó JSE sẽ tạo ra một không gian trong bộ nhớ để lưu trữ các hàm và các biến được khai báo để dùng trong giai đoạn Code Execution .
+ Trong giai đoạn Code Execution , JSE thực thi chương trình theo từng dòng
Vì vậy b và a sẽ nằm trong bộ nhớ từ đó mã sẽ được thực thi theo từng dòng..nhưng khi nó chạy đến dòng số 7 và nó hiểu được rằng mình muốn chạy hàm a và đây sẽ là nhưng điều xảy ra tiếp theo.
=> Một Execution Context (create and execute) mới được tạo ra đồng thời nó được đặt vào trong Execution Stack (stack nó giống như một hộp đựng sách , quyền này nằm trên quyển kia , quyển thêm vào mới nhất sẽ nằm trên cùng và cái đứng đầu là cái đang chạy ) vì vậy bất cứ khi nào bạn thực thi hoặc gọi một hàn trong JavaScript thì một Execution Context sẽ được tạo ra và được đưa vào The Execution Stack (ngăn xếp thực thi) .
Giống như Global Execution Context được tạo ra ngay từ đầu , Execution Context mới được tạo ra qua 2 giai đoạn và cứ thế trải qua giai đoạn Create Phase (JSE lấy biến và hàm trong hàm rồi thiết lập nó trong một vùng nhớ) tiếp tục nó sẽ thực thi từng dòng mã trong hàm tuy nhiên nếu trong quá trình chạy từng dòng mà nó gặp một lời gọi hàm khác thì nó sẽ dừng lại (đóng băng) và nó lại tiếp tục tạo ra một Execution Context mới và EC mới này tiếp tục được đặt vào trong Execution Stack và tạo ra theo 2 giao đoạn Create Phase và Code Execution.
=> Đây là những điều gì thực sự diễn ra khi gọi hàm trong JavaScript , mỗi hàm tạo ra một Execution Context mới và chạy qua 2 giai đoạn Create Phase và Code Execution
=> Khi b đã chạy xong , bởi vì nó ở trên cùng của Execution Stack thì nó sẽ được ném ra khỏi stack , sau đó chạy đến a và quay trở lại global.(Trong Execution Stack chỉ có EC nằm trên cùng mới được chạy)
=> Xét theo cấu trúc code mình viết thì a nằm phía bên trên b nhưng bạn hãy nhớ những gì đã xảy ra cả 2 hàm này đều đã có trong bộ nhớ khi bắt đầu tạo Global Execution Context và nó lưu các hàm và biến ở trong bộ nhớ (chú ý là nó chỉ lưu các hàm và các biến ở pham vi Global thôi nhé)
=> Trước hết a ở phía dưới sẽ gọi hàm a
Khi JS chạy đến hàm a thị Global Execution Context sẽ bị tạm dừng do JavaScript là một môi trường đơn luồng nó chỉ có thể thực thì một tác vụ tại một thời điểm...thì nó sẽ dừng không chạy đến dòng var d nữa mà những gì đang chạy là code nằm bên trong Execution Context của hàm a , vì khi a được gọi thì Execution Context của nó sẽ được đẩy lên đầu vào trong Execution Stack vì vậy khi a ở trên cùng của stack , nó sẽ bắt đầu chạy từng dòng của a.
- Khi nó chạy đến dòng gọi hàm b , thì Execution Context mới lại được tạo ra. và lại được đẩy lên đỉnh của The Execution Stack và chỉ khi nó chạy tất cả các dòng trong hàm b thì nó mới quay trở lại hàm a , bởi vì khi hàm chạy từng dòng xong thì Execution Context bọc nó sẽ bị bật ra khỏi The Execution Stack ..khi b được chạy xong thì quay trở lại hàm a và chạy tiếp dòng var d
- Khi a chạy xong thì nó mới chạy dòng var d (biến d ở phạm vi global)
Kết luận : Mỗi khi hàm được gọi thì một Execution Context mới sẽ được tạo ra cho hàm đó cùng với đó nó (Execution Context) tạo ra biến this cho hàm đó , các biến trong hàm được thiết lập vào trong bộ nhớ ở giai đoạn Create Phase..kế tiếp nó được đẩy lên trên cùng của The Execution Stack sau khi hàm này chạy nó bị đẩy ra khỏi stack và tiếp tục chạy dòng tiếp theo từng dòng một và đồng bộ.
Nhận xét
Đăng nhận xét