Làm sáng tỏ về Hoisting trong JavaScript



  • Hoisting và sự ngộ nhận chung trong cộng đồng Javascript

    • Hoisting là gì : Hoisting là một hành vi mặc định của Javascript di chuyển việc khai báo lên đầu trong scope của nó.

    Ví dụ như này :

    console.log(x); // sẽ in ra undefined thay vì lỗi 
    var x = 'abc'
    

    Sẽ được hiểu là :

      var x; //việc khai báo được đẩy lên đầu nên sẽ in ra giá trị undefined
      console.log(x);
      x = "abc";
    

    🚫 Tuy nhiên đây là một quan niệm sai lầm về hoisting

    Để làm rõ hơn về điều này chúng ta hãy xem cách : Javascript hoạt động như thế nào .

    Khi bộ máy JS xử lý đoạn code của bạn , nó tạo ra 1 cái gọi là bối cảnh thực thi (execution context). Có 2 quá trình liên quan đến việc tạo cái bối cảnh thực thi này :

    • Giai đoạn 1 (creation) : Trong giai đoạn này các biến và function được thêm vào bộ nhớ. Bộ máy JS sẽ đi qua một lượt đoạn code của bạn và thêm tất cả các biến vào bộ nhớ máy tính. Nhưng nó chưa gán giá trị cho các biến này. Trong khi đó các function thì lại được thêm toàn bộ vào bộ nhớ bao gồm cả tên và khối code bên trong nó.

    • Giai đoạn 2 (execution) : Trong giai đoạn này giá trị sẽ được gán cho các biến và function sẽ được gọi. Nên kể cả bạn khởi tạo 1 biến với giá trị ban đầu thì ở giai đoạn 2 này biến mới được gán giá trị. Ở giai đoạn 1 giá trị không được gán cho biến , nó được thêm vào bộ nhớ với giá trị khởi tạo là undefined.

    Quan niệm đúng về Hoisting

    Trước khi function được thực thi , nó đã được thêm vào bộ nhớ trong giai đoạn 1 (creation) nên bộ máy Javascript biết function này nằm ở đâu. Nó không chuyển cái function này lên trên đầu.

    logName() // in ra Nodemy
    function logName () { // Khai báo function logName
        console.log("Nodemy")
    }
    

    Còn về biến thì sao ?

    Quá trình cũng giống như vậy nhưng có 1 chút khác biệt. Các biến cũng được thêm vào bộ nhớ trong giai đoạn 1 nhưng không có giá trị nào được gán cho chúng. Trong JS khi một biến được khai báo mà không có giá trị nào bộ máy JS tự động thêm giá trị undefined . Điều này giải thích tại sao :

    console.log(coderName); 
    var coderName = "Nodemy"; 
    

    var coderName; 
    console.log(coderName); 
    

    có cùng kết quả là undefined.

    Thêm 1 ví dụ nữa để hiểu hơn :

    functionCoTen(); // in ra kết quả vì function đã được thêm vào bộ nhớ ở giai đoạn 1
    
    // TypeError: undefined is not a function
    functionKhongTen(); // in ra lỗi vì function đang được gán cho 1 biến mà ở giai đoạn 1 thì biến functionKhongTen mang giá trị undefined.
    
    function functionCoTen() {
        console.log("function có tên");
    }
    
    var functionKhongTen= function () {
        console.log("function không tên");
    };
    

    Đây là toàn bộ quá trình đã gây hiểu lầm cho nhiều người nghĩ rằng bộ máy JS thực sự đã di chuyển việc khai báo biến hay function lên trên đầu đoạn code của họ.

    JavaScript ES6 và Hoisting

    Từ es6 trở lên giới thiệu 2 từ khóa letconst để khai báo biến. Điểm khác biệt so với var là ở giai đoạn 1 (creation) chúng không được khởi tạo với giá trị undefined như với var. Thay vào đó: chúng được set 1 chế độ đặc biệt gọi là Temporal Dead Zone. Đây là 1 khoảng thời gian giữa việc khai báo và khởi tạo biến. Trong giai đoạn này bạn sẽ không thể truy cập vào biến đó được. Điều này có nghĩa là chúng vẫn tồn tại ở đó nhưng bạn sẽ không thể truy cập được cho đến khi bạn khởi tạo giá trị cho biến sẽ được thực hiện ở giai đoạn 2.

    console.log(coderName); // ReferenceError: Cannot access 'coderName' before initialization
    let coderName = "Lawrence Eagles";
    
    console.log(coderName); // ReferenceError: Cannot access 'coderName' before initializatio
    const coderName = "Lawrence Eagles"; 
    

    Nên cũng với ví dụ như trên với var thì với let và const sẽ in ra lỗi, phần nào giúp cho bạn tránh được lỗi khi viết chương trình Javascript của mình.

    nguồn : DEMYSTIFYING HOISTING IN JAVASCRIPT,
    Advanced JavaScript ES6 — Temporal Dead Zone, Default Parameters And Let vs Var — Deep dive!


Log in to reply