Học Javascript 4: Hiểu rõ khởi tạo và hoisting
Giới thiệu hoisting
Cho đoạn code sau:
Bạn có thể đoán được kết quả in ra console là gì?
Oke, bây giờ chúng ta thay đổi code một tý:
Lần này bạn đoán kết quả là gì nào?
Ở một số ngôn ngữ khác, nếu làm như vậy sẽ báo lỗi. Nhưng trong Javascript, chúng ta không thấy lỗi gì và nhận được giá trị là undefined. Một số tài liệu trên mạng sẽ giải thích hoisting là đưa tất cả khai báo lên trên đầu file, nhưng giải thích như vậy chưa đúng bản chất của vấn đề. Bởi vì code bạn viết được dịch sang mã máy, nên trong quá trình dich này sẽ xảy ra một số công việc bên trong nó. Chúng ta cùng tìm hiểu thực chất của vấn đề tại sao lại như vậy nhé!
Hoisting là gì?
Với Execution Context sẽ có 2 giai đoạn là Khởi tạo và Thực thi. Trong giai đoạn khởi tạo ta có thể mô phỏng lại những gì Execution Context thực hiện qua hình sau:
Ngoài việc tạo Global Object, this, Outer Environment như đã biết ở bài trước, thì sẽ có thêm công việc cài đặt ( chuẩn bị ) bộ nhớ cho hàm và biến. Tức là Syntax Parser sẽ đọc hết code có trong file và làm công việc này, chứ hoisting không phải là đưa tất cả code khai báo lên đầu file như chúng ta vẫn nghĩ.
Quay lại đoạn code này:
Khi chạy, ngay trước khi chạy từng dòng từ dòng 3, Execution Context đã tạo bộ nhớ cho biến homepage. Nhưng lúc này nó chưa thực hiện phép gán giá trị, do đó nó không biết giá trị của biến này là gì nên nó phải đặt cho một giá trị mặc định là undefined cho homepage. Còn với hàm lúc khai báo thì không có phép gán nên phải khởi tạo luôn phần body của hàm là
console.log('hello')
Sau khi khởi tạo xong thì mới tới giai đoạn là Thực thi chạy từng dòng từ dòng 3 xuống.
Undefined trong Javascript
Chúng ta đã biết là kết quả của đoạn code này là undefined:
var a console.log(a) // undefined
Và undefined là một keyword trong Javascript. Chúng ta có thể kiểu tra một biến là undefined hay không:
if ( a === undefined ){ console.log('a is undefined') }
Thậm chí có thể gán một biến bằng với undefined
var a = 5 a = undefined if ( a === undefined ){ console.log('a is undefined') }
Tips: Không nên gán giá trị của biến bằng undefined vì sẽkhó debug