Hiểu nhanh về Hoisting trong Javascript trong 5 phút

Hoisting là gì ? Hoisting trong Javascript hoạt động ra sao ?… thông qua bài viết này mình sẽ giải thích cho các bạn những câu hỏi trên , cùng xem lời giải như thế nào nhé .
tải xuống.png
Hoisting là gì ?

Hoisting là những vấn đề xoay quanh việc khai báo biến của Javascript , để hiểu rõ hơn chúng ta có thể hình dung như sau :

Khi chúng ta code một đoạn JavaScript(JS) , trình sẽ tạo ra một bối cảnh thực thi chung (Global execution context) bối cảnh này được chia làm 2 giai đoạn : Tạo và thực thi .Trong giai đoạn tạo , JS sẽ di chuyển các khai báo biến lên đầu của đoạn mã , giúp cho chương trình không bị lỗi khi sử dụng biến trước khi khai báo .Tính năng trên được gọi là Hoisting (tính năng lưu trữ trong javascript) .

Biến hoisting trong javascript

Nhờ tính năng Hoisting của JS bạn có thể đinh nghĩa một biến sau khi sử dụng .
Chúng ta có ví dụ sau :

// Gán nhưng chưa khai báo biến
domain = 'nodejs.vn';
 // Kết quả: Domain là nodejs.net
document.write("Domain là: " + domain);
// Khai báo
var domain;
// Kết quả: Domain là nodejs.net
document.write("<br/> Domain là: " + domain);

Nếu trong lúc khởi tạo mà chúng ta gán giá trị cho biến sẽ ra sao ?
Để trả lời cho câu hỏi trên chúng ta có ví dụ sau :

// Gán nhưng chưa khai báo biến
domain = 'nodejs.vn';
 
// Kêt quả: Domain là nodejs.vn
document.write("Domain là: " + domain);
// Khai báo
var domain = 'test.net';
 
// kêt quả: Domain là nodejs.vn
document.write("<br/> Domain là: " + domain);

Vậy nếu khai báo biến trước khi sử dụng thì kết quả như thế nào ?
Ví dụ:

// Khai báo
var domain;
 
// Gán nhưng chưa khai báo biến
domain = 'nodejs.vn';
 
// Kết quả: Domain là nodejs.vn
document.write("Domain là: " + domain);
 
// Kết quả: Domain là nodejs.vn
document.write("<br/> Domain là: " + domain);

Sử dụng từ khóa let và var trong Hoisting

Việc sử dụng letvar để khai báo biến trong hoisting của JS cũng sẽ có nhiều điểm khác biệt .

Sử dụng var: Nếu biến chưa gán giá trị thì sẽ trả về: undefined.

console.log(counter); // undefined
var counter = 1;

hoặc

var counter;
console.log(counter); // undefined
counter = 1;

Sử dụng let: Nếu biến chưa gán giá trị thì sẽ xuất hiện thông báo lỗi: Cannot access before initialization.

console.log(counter);
let counter = 1;

Kết quả trả về :

ReferenceError: Cannot access 'counter' before initialization

Bạn có thể lỗi trên rằng biến counter đã được định nghĩa trong bộ nhớ heap nhưng chưa được khởi tạo.

Hàm Hoisting trong javascript

JS sẽ lưu chữ các khai báo hàm giống như các biến . Nó sẽ di chuyển các khai báo hàm lên đầu của chương trình.
Chúng ta có ví dụ sau :

let x = 2,
    y = 1;
 
let result = add(x,y);
console.log(result);
 
function add(a, b){
    return a + b;
}

Đoạn code trên sử dụng hàm add rồi mới khai báo hàm sau . Khi chạy đoạn code trên ,không báo lỗi , Lý do là cơ chế hoisting của javascript đã di chuyển các khai báo hàm lên đầu rồi mới thực thi chương trình.

Hoisting trong biểu thức hàm

Biểu thức hàm hay còn gọi là function expressions. Nó là một hàm được khai báo bằng cách gán vào một biến.Ví dụ :

var add = function(x, y) {
    return x + y;
}

Chuyện gì sẽ xảy ra nếu ta sử dụng một function expressions trước rồi mới khai báo sau? Hãy xem ví dụ dưới đây.

let x = 2,
    y = 1;
 
let result = add(x,y);
console.log(result);
 
var add = function(x, y) {
    return x + y;
}

Khi chạy đoạn code sẽ báo lỗi : “TypeError: add is not a function”

Lý do rất đơn giản. Javascript sẽ xem biết add là một biến thông thường, nên khi nó đưa lên đầu thì sẽ là một biến chứ không phải là một hàm. Vì vậy, khi sử dụng sẽ xuất hiện lỗi add is not a function.

Hoisting function vs Hoisting variable

Trình biên dịch Javascript sẽ chuyển phần đinh nghĩa của hàm trước phần khai báo của biến, chúng ta có ví dụ sau :

var my_wallet;
my_wallet();
function my_wallet() {
  console.log('Money');
}
my_wallet = function() {
  console.log('Bitcoin');
}

Với đinh trên Output sẽ là Monney

Những hàm khai báo sau nếu trùng tên sẽ ghi đè lên hàm khai báo trước .
Ví dụ :

var my_wallet;
my_wallet();
function my_wallet(){
  console.log('Money');
}
my_wallet = function(){
  console.log('Diamond');
}
function my_wallet(){
  console.log('Bitcoin');
}

Kết quả trả về là :Bitcoin

Kết luận :
Kết thúc bài mình mong các bạn có thể hiểu được phần nào độ “Vi diệu ” của Javascript và chúng ta đi đến những kết luận sau :

Trình biên dịch của Javascript sẽ chuyển phần khai báo của biến và hàm lên trên top, nó được gọi là Hoisting
Chỉ có phần khai báo được đưa lên đầu, không phải phần gán giá trị
Phần khai báo hàm được đưa lên trước phần khai báo của biến