Hoisting trong javascript

Javascript có một khái niệm khá kỳ quặc nhưng cũng rất quan trọng, đó chính là hoisting. Hôm nay mình sẽ giải thích cặn kẽ cho mọi người thế nào là hoisting và cách để chúng ta có thể tránh được những vẫn đề dễ gặp phải nếu không cẩn thận với nó.

Đầu tiên, mọi người hãy xem ví dụ sau đây:

function test(param) {
    console.log(param);
}

test("hello world"); // hello world

Có lẽ mọi người có thể dễ dàng đoán được rằng function "test" sẽ in ra gì rồi 😄. Tiếp theo các bạn hãy đoán xem kết quả mà function "test" sẽ in ra là gì trong ví dụ tiếp theo là gì nhé.

test("hello world"); // ?

function test(param) {
    console.log(param);
}

Có lễ một số người, nhất là các bạn newbie sẽ ngạc nhiên khi biết rằng đoạn script trên vẫn sẽ in ra chữ "hello world" giống với ví dụ đầu tiên ! và đó chính là Hoisting.

Vậy Hoisting là gì ?

Hiểu một cách đơn giản thì javascript sẽ đưa việc "khởi tạo" các biến và function lên trên đầu function (scope) chứa các biến và function đó.

Bây giờ các bạn hãy nhìn lại vào ví dụ số 2, tuy ta gọi function test đằng trước câu lệnh khởi tạo function test. Tuy nhiên, javascript sẽ tự động đẩy câu lệnh khởi tạo test lên trên cùng đoạn script, vậy nên đoạn lệnh test("hello world");vẫn sẽ chạy như bình thường.

Vậy chúng ta đã cơ bản hiểu được các javascript xử lý việc khai báo các biến và function, bây giờ các bạn hãy thử đoán tiếp kết quả của đoạn script số 3 này nhé: 😜


    console.log(myName);
    
    var myName = "huq"; // ?

Có lẽ không ít bạn sẽ nghĩ rằng đoạn script trên sẽ in ra "huq" phải không 😅😅. Thực ra kết quả sẽ là undefined.

Như mình đã giải thích ở trên, javascript chỉ đẩy việc khởi tạo lên đầu, nhưng việc gán giá trị thì không đâu nhé 😆😆. Chính vì vậy mà ví dụ số 3 sẽ in ra undefined bởi vì biến myName sẽ chỉ được gán cho giá trị "huq" khi dấu = xuất hiện đằng trược nó. Túm lại thì ví dụ số 3 có thể được viết như sau:

    var myName; // khởi tạo myName

    console.log(myName); // undefined (myName chưa có giá trị)
    
    myName = "huq"; // gán myName cho giá trị"huq"

Có một lưu ý nhỏ mã các bạn cũng nên để ý đó là function sẽ được đưa lên trên cả các biến nên mọi người hãy cẩn thận nhé 😄.

Hoisting với let và const

Trước tiên, mình sẽ nói qua về letconst nhưng nếu các bạn chưa biết về es6 thì có thể bỏ qua phần này nhé. Cơ bản thì 2 từ khóa này cũng dùng để khởi tạo biến giống như var nhé. Nhưng var sẽ tạo property cho Global object (Window) còn letconst thì không.

Cơ bản thì letconst vẫn sẽ được javascript hoist lên đầu function chứa chúng. Nhưng bạn sẽ gặp lỗi Cannot access '...' before initialization nếu bạn khởi tạo một biến với const mà không gán giá trị cho nó.

    console.log(myAge);

    const myAge = 20; // Uncaught ReferenceError: Cannot access 'myAge' before initialization

Tương tự:

    const myAge;
    
    console.log(myAge);

    myAge = 20; // Uncaught SyntaxError: Missing initializer in const declaration

Hai Vậy nên, các bạn hãy nhớ gán giá trị cho các biến được khởi tạo bằng const nhé !.


Nguồn tham khảo: medium.