Hoisting trong JavaScript
Bài đăng này đã không được cập nhật trong 5 năm
Javascript được mệnh danh là "The World's Most Misunderstood Programming Language - Ngôn ngữ lập trình dễ gây hiểu lầm nhất". Một trong số những cái hay ho mà làm cho javascript trông như có vẻ sai sai đó chính là hoisting
Nếu bạn là người mới học hoặc không code javascript nhiều thì rất có thể bạn sẽ thấy lạ lẫm với khái niệm hoisting. Vì vậy nếu bạn muốn tìm hiểu sâu hơn về javascript thì bạn nên biết về khái niệm hoising này nhé.
Khái niệm hoisting
Về cơ bản, khi Javascript compile code, tất cả các biến được khai báo sử dụng var
sẽ được nâng lên trên cùng của function hoặc trên cùng của scope nếu nó được khai báo bên ngoài function. Và việc đẩy khai báo biến lên đầu được gọi là hoisting.
Khai báo function
cũng là hoisting, thậm trí nó sẽ được đẩy lên trên cả khai báo biến.
Để hiểu rõ hơn, chúng ta đi xét một vài ví dụ sau.
console.log(name)
var name = 'th';
Kết quả của console.log(name) là gì?
Uncaught ReferenceError: name is not defined
th
undefined
Kết quả chính xác là đáp án thứ 3.
Như đã nới ở trên, khi biên dịch phần khai báo biến sẽ được đẩy lên trên. Tuy nhiên điều quan trọng cần các bạn cần chú ý là chỉ phần khai báo biến được đẩy lên trên, không phải cả phần gán giá trị
Kết quả là undefined
là vì khi biên dịch việc khai báo biến name
sẽ được đặt lên đầu, và nó sẽ nằm trên câu lệnh console.log(name)
, chính vì vậy sẽ không bị lỗi Uncaught ReferenceError: name is not defined
vì khi console.log(name)
thì biến name đã tồn tại. Nhưng biến name lúc này chỉ được khai báo chứ chưa được gán giá trị, chính vì vậy giá trị nó là undefined
Để dễ hiểu hơn thì ví dụ trên sau khi biên dịch sẽ có thứ tự như thế này.
var name
console.log(name)
name = 'th';
Giờ thì rõ rồi phải không nào.
Xét ví dụ với function
function hey() {
console.log('hey ' + name);
};
hey();
var name = 'th';
Khi chạy name
khi được in ra sẽ vẫn là undefined
. Vì nó thực sự sẽ như sau khi biên dịch
function hey() {
console.log('hey ' + name);
};
var name;
hey();
name = 'th';
Vào thời điểm hàm hey()
được gọi. Biến name
đã được khai báo, nhưng chưa được gán giá trị do dậy kết quả là undefined
. Có một vài biến thể của điều này, xảy ra khi khai báo biến trong biểu thức IIFE . IIFE chắc hẳn cũng là một khái niệm lạ lẫm, nhưng mình sẽ nói đến nó trong một bài nào đó sau này.
Tuy hoisting sẽ làm cho việc dụng trước - khai báo sau
lại không gây ra lỗi )))), nhưng sẽ là tốt nhất nếu chúng ta đẩy việc khai báo biến trên đầu,giống như hoisting làm, điều đó sẽ làm code dễ đọc hơn và giảm thiểu được những lỗi không đáng có.
Vậy đối với let và const thì sao?
All declarations (var, let, const, function, function*, class) are "hoisted" in JavaScript.
Tất cả các khai báo var, let, const, function, function*, class
trong Javascript đều được hoisting.
Sự khác biệt giữa khai báo var
so với let và const
là giá trị khởi tại. Đối với var
giá trị khởi tạo là undefined
trong khi đó với let và const
sẽ thorw ra lỗi Reference error
khi bạn chỉ khai báo mà chưa gán giá trị.
Có một chú ý nhỏ là vì const
phải được gián giá trị cùng với việc khai báo. Nên khi hoisting sẽ không được chuyển thành dạng const name; name = 'th';
mà sẽ chỉ là const name = 'th'
. Lý do thì hết sức rõ ràng rồi, const
là hằng số mà, nó đâu có gán được giá trị khác, nên khi khởi tạo const
sẽ được gán giá trị luôn.
Kết luận
Một khái niêm đơn giản, nhưng sẽ rất quan trọng nếu bạn muốn học Javascript một cách bản. Ngoài hoisting ra còn nhiều khái niệm khác để các bạn tìm hiểu nhé
- IIFE
- First-class functions
- Function Expression
- Function scope
- Lexical scope
- Closure
- Block scope
- this
- Prototype
- New
- Function statement
- Function constructor
All rights reserved