Hiện tượng này được gọi là: JavaScript Variable Hoisting .
Tại thời điểm nào bạn không truy cập vào biến toàn cục trong hàm của bạn; bạn chỉ truy cập vào value
biến cục bộ.
Mã của bạn tương đương với mã sau:
var value = 10;
function test() {
var value;
console.log(value);
value = 20;
console.log(value);
}
test();
Bạn vẫn ngạc nhiên khi nhận được undefined
?
Giải trình:
Đây là điều mà mọi lập trình viên JavaScript sớm hay muộn đều gặp phải. Nói một cách đơn giản, bất kỳ biến nào bạn khai báo luôn được đưa lên đầu trang đóng cục bộ của bạn. Vì vậy, mặc dù bạn đã khai báo biến sau lần console.log
gọi đầu tiên , nó vẫn được coi là bạn đã khai báo trước đó.
Tuy nhiên, chỉ có phần khai báo đang được kéo lên; mặt khác, không phải là nhiệm vụ.
Vì vậy, khi bạn gọi lần đầu tiên console.log(value)
, bạn đang tham chiếu đến biến được khai báo cục bộ của mình, biến này chưa được gán gì cho nó; do đó undefined
.
Đây là một ví dụ khác :
var test = 'start';
function end() {
test = 'end';
var test = 'local';
}
end();
alert(test);
Bạn nghĩ điều này sẽ cảnh báo điều gì? Không, đừng chỉ đọc, hãy nghĩ về nó. Giá trị của là test
gì?
Nếu bạn nói bất cứ điều gì khác hơn start
, bạn đã sai. Đoạn mã trên tương đương với mã này:
var test = 'start';
function end() {
var test;
test = 'end';
test = 'local';
}
end();
alert(test);
để biến toàn cục không bao giờ bị ảnh hưởng.
Như bạn có thể thấy, bất kể bạn đặt khai báo biến của mình ở đâu, nó luôn được đưa lên đầu trang đóng cục bộ của bạn.
Lưu ý phụ:
Điều này cũng áp dụng cho các chức năng.
Hãy xem xét đoạn mã này :
test("Won't work!");
test = function(text) { alert(text); }
điều này sẽ cung cấp cho bạn một lỗi tham chiếu:
Uncaught ReferenceError: test không được xác định
Điều này ném ra rất nhiều nhà phát triển, vì đoạn mã này hoạt động tốt:
test("Works!");
function test(text) { alert(text); }
Lý do cho điều này, như đã nói, là vì phần chuyển nhượng không được nâng lên. Vì vậy, trong ví dụ đầu tiên, khi test("Won't work!")
được chạy, test
biến đã được khai báo, nhưng vẫn chưa được gán hàm cho nó.
Trong ví dụ thứ hai, chúng tôi không sử dụng phép gán biến. Thay vào đó, chúng tôi đang sử dụng cú pháp khai báo hàm thích hợp, cú pháp này sẽ đưa hàm hoàn toàn vào.
Ben Cherry đã viết một bài báo xuất sắc về vấn đề này, có tiêu đề thích hợp JavaScript Scoping and Hoisting .
Đọc nó. Nó sẽ cung cấp cho bạn toàn cảnh chi tiết.