Khi tìm hiểu Javascript, bạn sẽ biết được rằng JS là ngôn ngữ lập trình kiểu thông dịch tương tự như Ruby. Mỗi khi chạy ứng dụng, bộ thông dịch trong JS engine sẽ thực thi các câu lệnh từ trên xuống dưới. Tuy nhiên, trong Javascript tồn tại thêm một cơ chế rất đặc biệt nữa, đó là khái niệm “Hoisting” hay “hoisted” cũng vậy.
Hoisting là cơ chế chỉ có trong Javascript, nó khiến cho nhiều bạn mới tiếp cận JS cảm thấy bối rối, khó hiểu khi gặp lỗi liên quan đến hoisting.
Bài viết này, chúng ta cùng tìm hiểu xem Hoisting là gì? Tại sao chúng ta cần phải biết?
Nội dung chính của bài viết
Hoisting Javascript là gì?
Bất cứ khi nào chương trình của bạn chạy, Javascript sẽ phân tích cú pháp mã nguồn trước khi thực thi. Trong giai đoạn phân tích này, nếu trình phân tích sẽ kiếm tra từng dòng mã, nếu phát hiện bất kỳ lỗi lầm nào, chương trình sẽ dừng.
Giả sử mã nguồn của bạn OK, không có sai sót nào cả, trình thông dịch Javascript sẽ di chuyển các hàm, biến được khai báo lên đỉnh của mã nguồn. Vì vậy, theo cách này, chúng ta có thể sử dụng các biến hay hàm trước khi đến đoạn khai báo nó trong mã nguồn.
Vậy cơ chế hoisting là gì? Hoisting là cơ chế mà trình thông dịch di chuyển tất cả biến, hàm được khai báo lên đầu mã nguồn. Bất kể phạm vi của chúng là toàn cục (global) hay cục bộ (local), chúng đều được trình thông dịch đưa lên đầu (trong phạm vi của chúng).
Variable hoisting
Chúng ta sẽ cùng tìm hiểu sự khác nhau của cơ chế hoisting giữa var
và let
.
Sử dụng var
language = 'Cơ chế hoisting trong javascript' console.log(language); var language;
Kết quả nhận được là dòng chữ:
// Cơ chế hoisting trong javascript
Cơ chế hoisting sẽ đưa các biến được khai báo bằng từ khóa var
lên đầu và khởi tạo giá trị underfined
. Giá trị undefined
sẽ tồn tại cho tới khi trình thông dịch gặp dòng lệnh gán trị cho biến đó.
Đoạn code trên sẽ tương tự như sau:
var language = undefined; language = 'Cơ chế hoisting trong javascript' console.log(language);
Sử dụng let
hay const
?
Trong trường hợp bạn khai báo một biến nhưng sử dụng từ khóa let
thì sao?
Chúng ta cùng xem xét đoạn code sau:
console.log(name); let name = "vntalking";
Ngay lập tức, bạn gặp lỗi sau:
error: ReferenceError: can't access lexical declaration 'name' before initialization
Chuyện gì đang xảy ra vậy? từ khóa let không hỗ trợ hoisting sao?
Câu trả lời là: các biến được khai báo bằng let/const
vẫn được cơ chế hoisting đưa lên đầu mã, nhưng chúng không được khởi tạo. Đây chính là điểm khác biệt.
Các biến được khai báo bằng từ khóa var
sẽ được khởi tạo thành underfined
. Còn với let/const
thì không.
Hoisting function
Cơ chế hoisting function hoàn toàn tương tự như với biến. Tuy nhiên, chỉ có một điểm lưu ý là cơ chế hoisting sẽ di chuyển phần định nghĩa của hàm trước phần định nghĩa biến.
Chúng ta xem xét ví dụ sau:
var makeMoney; makeMoney(); function makeMoney() { console.log('Dolar'); } makeMoney = function() { console.log('Diamond'); }
Kết quả khi chạy chương trình sẽ in ra dòng “Dolar”:
Dolar
Tổng kết
Tóm lại hoisting là một cơ chế đặc biệt mà chỉ có JS mới có. Chính vì điều này mà khiến cho nhiều bạn developer cảm thấy “thật rối bời”. Bời vì họ quen với việc phải khai báo xong rồi mới sử dụng. Thực ra, đây cũng là một cách làm tốt, tránh gặp lỗi tiềm tàng khi lạm dụng hoisting.
Các nhà phát triển JS cũng hiểu được tâm tư đó nên cho ra đời chế độ “strict mode“. Trong chế độ này bạn không thể sử dụng cơ chế hoisting.
😌 Đọc thêm:
Bình luận. Cùng nhau thảo luận nhé!