Execution context và scope trong JavaScript

Khái niệm execution context vô cùng quan trọng trong JavaScript. Execution context của một biến hay một hàm định nghĩa dữ liệu mà nó truy cập tới cũng như là cách nó cư xử như thế nào. Mỗi execution context kết hợp với variable object, công việc chính của đối tượng này là định nghĩa tất cả các biến và hàm tồn tại. Đối tượng này thì không thể truy cập bằng code nhưng nó được sử dụng ngầm để quản lý dữ liệu

Execution context toàn cục là cái ngoài cùng nhất. Tùy thuộc vào môi trường mà ECMAScript thực thi, đối tượng mô tả context có thể khác nhau. Trong các trình duyệt web, chúng ta có một execution context toàn cục là đối tượng window, do đó tất cả các biến toàn cục và hàm được tạo như là thuộc tính và phương thức của đối tượng window. Khi một execution context thực thi xong hết code của nó, nó sẽ bị hủy cùng với tất cả các biến và hàm định nghĩa bên trong nó (các execution context toàn cục sẽ không bị hủy cho đến khi ứng dụng thoát như là trang web bị đóng hoặc trình duyệt web tắt)

Mỗi hàm có execution context cho chính nó. Bất cứ khi nào việc thực thi code trong hàm xảy ra, execution context của hàm sẽ được đẩy vào stack context. Sau khi hàm hoàn tất việc thực thi, stack đẩy execution context này ra, trả điều khiển cho execution context trước đó. Tiện ích này điều khiển dòng thực thi chương trình thông qua chương trình ECMAScript

Khi code thực thi trong một execution context, một thứ khác được gọi là scope chain cho các đối tượng biến được tạo ra. Mục đích của scope chain là cung cấp thứ tự truy cập đến tất cả các biến và các hàm mà một execution context truy cập đến. Phía trước của scope chain luôn luôn là biến đối tượng của execution context mà code đang thực thi. Nếu execution context là một hàm, khi đó đối tượng activation được sử dụng như là varibale object. Một đối tượng activation bắt đầu với một biến đơn được định nghĩa gọi là arguments (cái này không tồn tại cho execution context toàn cục). Biến đối tượng kế tiếp trong chuỗi là từ execution context đang chứa và biến đối tượng kế tiếp sau đó là từ execution context kế tiếp. Kiểu này nó cứ tiếp tục cho đến khi execution context toàn cục đạt đến, biến đối tượng của execution context toàn cục luôn là cái cuối cùng trong scope chain.

Những định danh được giải quyết bằng cách lục lội trong scope chain để tìm kiếm tên định danh. Việc tìm kiếm luôn bắt đầu ở phía trước của chuỗi và tiến về phía sau cho đến khi định danh được tìm thấy

Chúng ta cùng xem đoạn mã sau

var color = “blue”;
                   
function changeColor(){
    if (color === “blue”){
        color = “red”;
    } else {
        color = “blue”;
    }
}
                   
changeColor(); 

Trong đoạn mã trên, hàm changeColor() có scope chain với 2 đối tượng trong nó: biến đối tượng (đối tượng arguments) và biến đối tượng của execution context toàn cục. Do đó biến color có thể truy xuất bên trong hàm bởi vì nó có thể tìm thấy trong scope chain

Hơn nữa, những biến được định nghĩa cục bộ có thể sử dụng thay thế cho nhau với những biến toàn cục trong execution context cục bộ. Ví dụ như sau:

var color = “blue”;
                   
function changeColor(){
    var anotherColor = “red”;
                   
    function swapColors(){
        var tempColor = anotherColor;
        anotherColor = color;
        color = tempColor;
        
        //color, anotherColor, and tempColor có thể truy cập ở đây
    }
                   
    //color and anotherColor có thể truy cập ở đây, nhưng tempColor thì không thể
    swapColors();
}
                   
//chỉ có color có thể truy cập ở đây
changeColor(); 

Chúng ta có ba execution context trong đoạn mã trên: execution context toàn cục, execution context cục bộ của hàm changeColor(), và execution context cục bộ của hàm swapColors(). Execution context toàn cục có một biến là color và một hàm là changeColor(). Execution context cục bộ của changeColor() có một biến tên là anotherColor và một hàm là swpColors() nhưng nó có thể truy xuất biến color từ execution context toàn cục. Execution context cục bộ của hàm swapColors() có một biến tên là tempColor chỉ có thể bên trong execution context này. Không execution context toàn cục cũng không execution context cục bộ của swapColors() truy xuất tempColor. Bên trong swapColors(), những biến của 2 context kia có thể truy xuất một cách đầy đủ bởi vì chúng là những execution context cha

Trong hình vẽ trên, những hình chữ nhật mô tả những execution context xác định. Những execution context có thể truy cập mọi thứ từ tất cả execution context bên ngoài qua scope chain, nhưng những context bên ngoài không thể truy xuất bất cứ thứ gì bên trong execution context bên trong. Sự kết nối giữa các context là tuyến và có thứ tự. Mỗi execution context có thể tìm phía trên của scope chain cho các biến và các hàm nhưng không có execution context có thể tìm phía dưới của scope chain bên trong execution context khác. Chúng ta có ba đối tượng trong scope chain của execution context của swapColors(): biến đối tượng swapColors(), biến đối tượng từ changeColor() và biến đối tượng toàn cục. Execution context cục bộ của swapColors(0 bắt đầu tìm biến và những tên hàm trong biến đối tượng của chính nó trước khi nó di chuyển cùng với chain. Scope chain cho execution context changeColor() chỉ có 2 đối tượng: biến đối tượng của chính nó là biến đối tượng toàn cục. Điều này có nghĩa là nó không thể truy xuất execution context của swapColors

Những đối số của hàm được xem như là những biến và theo cùng những quy tắc truy xuất như bất kì những biến khác trong execution context


Leave a Reply

Your email address will not be published. Required fields are marked *