Javascript Hoisting là gì?

ant-weight-lifting-javascript-hoistingMột đặc điểm nhỏ của javascript nhưng đôi lúc khiến lập trình viên gặp những rắc rối khó hiểu.

Giới thiệu

Hoisting là khái niệm chỉ việc mọi khai báo biến ( với từ khóa var ) sẽ được chuyển lên trên cùng của hàm .

Để kiểm tra, tôi thử ví dụ sau trong Chrome Developer Tools:

Bạn đang đọc: Javascript Hoisting là gì?

(function(){
	console.log(foo);
})();

>> ReferenceError : foo is not defined
Oops ! Tất nhiên là nó sẽ ra lỗi ? ! @ # USD % Hãy thử một ví dụ khác :

(function(){
	console.log(foo);
	var foo = "hello";
})();
>> undefined

‘undefined’ thay vì lỗi? Nguyên nhân là do việc khai báo biến foo đã được chuyển lên trên cùng. Đoạn code trên thực tế được chuyển thành như sau khi chạy:

(function(){
	var foo;
	console.log(foo);
	foo = "hello";
})();
>> undefined

Tất nhiên chỉ có khai báo biến được chuyển lên đầu hàm, còn những biểu thức gán sẽ vẫn nằm tại vị trí cũ. Đối với những trường hợp biến được khai báo trong những khối lệnh như if, for, while, switch, … cũng không ngoại lệ. Đó là tác dụng ( hoặc cũng hoàn toàn có thể là nguyên do ) của việc :

javascript không có block-level scope .

(function(){
	console.log(foo);
    if(false){
		var foo = "hello";
	}
})();
>> undefined

Function Declaration và Function Expression

Trước tiên ta cần phân biệt hai khái niệm này :

// Function Declaration:
function foo(){
    // code
}
// Function Expression:
var foo = function(){
	// code
};

Cả hai phương pháp tạo hàm này đều bị ảnh hưởng bởi “hoisting”, tuy nhiên có một điểm khác nhau quan trọng giữa chúng.
Function Declaration: toàn bộ hàm sẽ được di chuyển lên đầu. Nghĩa là bạn có thể sử dụng được hàm trước khi nó được định nghĩa.
Function Expression: chỉ có phần khai báo được di chuyển lên đầu.

Và …

what does it matter meme

Để vấn đáp, bạn hoàn toàn có thể xem và Dự kiến đoạn code sau sẽ in gì ra màn hình hiển thị :

(function(){
	var foo = 1;
	(function(){
		console.log(foo);
		var foo = 2;
	})();
	console.log(foo);
})();

Nếu chưa biết về hoisting, bạn hoàn toàn có thể đưa ra hiệu quả sai. Câu vấn đáp đúng mực là ‘ undefined ’. Nguyên nhân là do bạn khai báo lại ( với từ khóa var ) biến foo bên trong hàm con. Nếu bạn không khai báo lại, hàm con sẽ sử dụng biến foo của ngữ cảnh bên ngoài .
Một ví dụ khác với hàm :

(function(){
    console.log(foo()); // 3

    var foo = function() {
        return 1;
    };
    function foo() {
        return 2;
    };
    function foo() {
        return 3;
    };
})();
>> 3

Kết quả xuất ra có thể nằm ngoài dự đoán của bạn do hàm được định nghĩa cuối cùng sẽ ghi đè lên các hàm cùng tên được định nghĩa trước nó.

Hãy tưởng tượng bạn có một đoạn javascript rất dài, bạn khai báo biến tại những chỗ mà bạn khởi đầu dùng nó, bạn quên rằng tên biến này đã được dùng hoặc nhầm lẫn giữa những scope với nhau. Kết quả là nó nhảy ra một lỗi hoặc tệ hơn là nó … bí mật chờ đón và Open khi đưa cho người mua. Vậy một best practice mà bạn nên tập từ giờ đây là :

Luôn khai báo biến / hàm trên cùng thay vì để trình duyệt làm giùm bạn .

YinYangIt’s Blog

Bình chọn

Share this:

Thích bài này:

Thích

Đang tải …