Hãy cùng Thế giới JS tìm hiểu sâu hơn về Hoisting trong javascript, Nó là một khái niệm cho phép chúng ta trích xuất các giá trị của biến và hàm ngay cả trước khi khởi tạo/gán giá trị mà không gặp lỗi và điều này xảy ra do giai đoạn 1 (giai đoạn tạo bộ nhớ) của Bối cảnh thực thi.
Để chạy code js ví dụ dưới đây, các bạn có thể vào các trang web chạy javascript online để test nha.
Trong JavaScript, Hoisting là hành vi mặc định để di chuyển tất cả các khai báo lên đầu một phạm vi trước khi thực thi code. Về cơ bản, nó mang lại cho chúng ta một lợi thế là bất kể hàm và biến được khai báo ở đâu, chúng đều được chuyển lên đầu phạm vi của chúng bất kể phạm vi của chúng là toàn cục hay cục bộ.
Nó cho phép chúng ta gọi các hàm trước khi viết chúng vào code của chúng ta.
Lưu ý: JavaScript chỉ Hoisting các khai báo, không khởi tạo.
JavaScript phân bổ bộ nhớ cho tất cả các biến và hàm được khai báo trong chương trình trước khi thực thi.
Hãy cùng chúng tôi hiểu chính xác điều này là gì!
Sau đây là trình tự diễn ra việc khai báo và khởi tạo biến.
Khai báo -> Khởi tạo/Gán -> Sử dụng
// https://vpsus.vn/ // https://www.facebook.com/groups/893052378563701 // https://twitter.com/thegioijs let a; // Declaration a = 100; // Assignment console.log(a); // Usage
Tuy nhiên, vì JavaScript cho phép chúng ta đồng thời khai báo và khởi tạo các biến, nên đây là mẫu được sử dụng nhiều nhất:
let a = 100;
Lưu ý: Luôn nhớ rằng trong nền Javascript đầu tiên khai báo biến và sau đó khởi tạo chúng. Bạn cũng nên biết rằng các khai báo biến được xử lý trước khi bất kỳ code nào được thực thi.
Tuy nhiên, trong javascript, các biến không được khai báo không tồn tại cho đến khi code gán chúng được thực thi. Do đó, việc gán một giá trị cho một biến không được khai báo sẽ ngầm tạo ra nó như một biến toàn cục khi thực thi phép gán. Điều này có nghĩa là tất cả các biến không được khai báo đều là biến toàn cục.
// https://vpsus.vn/ // https://www.facebook.com/groups/893052378563701 // https://twitter.com/thegioijs // Hoisting function codeHoist(){ a = 10; let b = 50; } codeHoist(); console.log(a); // 10 console.log(b); // ReferenceError : b is not defined
Đầu ra:
10 ReferenceError: b is not defined at <anonymous>:15:13 at dn (<anonymous>:16:5449)
Giải thích: Trong mẫu code trên, chúng tôi đã tạo một hàm gọi là codeHoist() và trong đó chúng tôi có một biến mà chúng tôi không khai báo bằng cách sử dụng let/var/const và một biến let b. Biến không được khai báo được gán phạm vi toàn cầu bởi javascript do đó chúng tôi có thể in nó bên ngoài hàm, nhưng trong trường hợp biến b phạm vi bị giới hạn và nó không có sẵn bên ngoài và chúng tôi nhận được ReferenceError.
Lưu ý: Có sự khác biệt giữa ReferenceError và lỗi không xác định. Lỗi không xác định xảy ra khi chúng ta có một biến không được định nghĩa hoặc được khai báo rõ ràng là loại không xác định. ReferenceError được đưa ra khi cố gắng truy cập một biến chưa được khai báo trước đó.
1.Trong ES5
Khi chúng ta nói về ES5, biến xuất hiện trong đầu chúng ta là var. Hoisting với var hơi khác so với let/const. Hãy sử dụng var và xem cách cẩu hoạt động:
// https://vpsus.vn/ // https://www.facebook.com/groups/893052378563701 // https://twitter.com/thegioijs // var code (global) console.log(name); // undefined var name = 'vpsus.vn';
Đầu ra:
undefined
Giải thích: Trong đoạn code trên, chúng tôi đã cố gắng dùng biến name chưa được khai báo và gán muộn hơn so với việc sử dụng nó, trình biên dịch cung cấp cho chúng tôi biến name là không xác định(undefined) điều mà chúng tôi không mong đợi vì lẽ ra chúng tôi đã gặp phải ReferenceError khi chúng tôi cố gắng sử dụng biến tên ngay cả trước đó khai báo nó.
Nhưng trình thông dịch thấy điều này khác, đoạn code trên được thấy như thế này:
// https://vpsus.vn/ // https://www.facebook.com/groups/893052378563701 // https://twitter.com/thegioijs // how interpreter sees the above code var name; console.log(name); // undefined name = 'vpsus.vn';
Đầu ra:
undefined
Biến trong phạm vi hàm
Hãy xem cách các biến trong phạm vi hàm được Hoisting.
// https://vpsus.vn/ // https://www.facebook.com/groups/893052378563701 // https://twitter.com/thegioijs // Function scoped function fun(){ console.log(name); var name = 'vpsus.vn'; } fun(); // Undefined
Đầu ra:
Undefined
Không có sự khác biệt ở đây vì khi so sánh với code mà chúng tôi đã khai báo biến trên toàn cầu, chúng tôi nhận được code không được xác định vì code mà trình thông dịch nhìn thấy là:
// https://vpsus.vn/ // https://www.facebook.com/groups/893052378563701 // https://twitter.com/thegioijs function fun(){ var name; console.log(name); name = 'vpsus.vn'; } fun(); // undefined
Đầu ra:
undefined
Để tránh cạm bẫy này, chúng ta có thể đảm bảo khai báo và gán biến cùng lúc trước khi sử dụng nó . Một cái gì đó như thế này:
// https://vpsus.vn/ // https://www.facebook.com/groups/893052378563701 // https://twitter.com/thegioijs // in order to avoid it function fun(){ var name = 'vpsus.vn'; console.log(name); //vpsus.vn } fun();
Đầu ra:
Wikicode.dev
2.Trong ES6
Let: Chúng ta biết rằng các biến được khai báo với từ khóa let là phạm vi khối chứ không phải phạm vi hàm và do đó không có vấn đề gì khi nói đến Hoisting.
Thí dụ:
// https://vpsus.vn/ // https://www.facebook.com/groups/893052378563701 // https://twitter.com/thegioijs //let example(global) console.log(name); let name='vpsus.vn'; // ReferenceError: name is not defined
Đầu ra:
ReferenceError: name is not defined
Giống như trước đây, đối với từ khóa var, chúng tôi hy vọng đầu ra của console log sẽ không được xác định(undefined). Tuy nhiên, vì es6 let không chấp nhận chúng tôi sử dụng các biến không được khai báo, nên trình thông dịch sẽ đưa ra lỗi Tham chiếu một cách rõ ràng. Điều này đảm bảo rằng chúng tôi luôn khai báo biến của mình trước.
const hoạt động tương tự như let khi Hoisting nha ae.
Trên đây là tất cả những gì về Hoisting trong javascript mà bạn cần biết. Nếu bạn có bất kỳ câu hỏi liên quan tới Hoisting, hãy chủ động liên hệ và inbox cho chúng tôi, để giúp đỡ bạn sớm nhất
Tiếp theo, hãy cùng Thế giới JS tìm hiểu thêm các kiến thức về Javascript trong các bài tiếp theo trong series học miễn phí Javascript từ cơ bản tới nâng cao.
Nếu bạn cảm thấy hữu ích và yêu thích Thế giới JS, hãy tham gia và theo dõi chúng tôi để nhận thêm nhiều kiến thức MIỄN PHÍ hơn nữa nhé:
Share to learn more than!