PHẦN CƠ BẢN
VÒNG LẶP
DATA TYPES
EVENTS
DOM
BOM
OBJECT
BỔ SUNG
THỰC HÀNH
JAVASCRIPT CĂN BẢN
CÁC CHỦ ĐỀ
BÀI MỚI NHẤT
MỚI CẬP NHẬT

Cơ chế hoạt động của hoisting trong Javascript

Trong bài này chúng ta sẽ tìm hiểu hoisting trong Javascript, qua đó sẽ giúp bạn hiểu khái niệm hosting là gì, và cơ chế hoạt động của hosting trong ngôn ngữ javascript.

test php

banquyen png
Bài viết này được đăng tại freetuts.net, không được copy dưới mọi hình thức.

Hoisting là vấn đề liên quan đến cách khai báo biến trong Javascript. Theo quy tắc chung của hầu hết các ngôn ngữ lập trình, để sử dụng một biến thì bạn phải khai báo nó trước. Nhưng javascript thì lại khác, có một số trường hợp bạn có thể sử dụng biến rồi mới khai báo sau. Lý do là gì thì chúng ta cùng tìm hiểu ngay nhé.

1. Hoisting trong javascript là gì?

Khi bạn thực thi một đoạn mã javascript thì trình biên dịch sẽ tạo ra một bối cảnh thực thi chung, ta gọi là global execution context.

Bối cảnh thực thi này sẽ có hai giai đoạn, thứ nhất là tạo và thứ hai là thực thi.

Bài viết này được đăng tại [free tuts .net]

Trong giai đoạn tạo thì javascript sẽ di chuyển các khai báo biến lên đầu của đoạn mã, giúp cho chương trình không bị lỗi khi sử dụng biến trước khi khai báo. Tính năng này ta gọi là tính năng lưu trữ trong javascript, và trong tiếng Anh gọi là Hoisting.

2. Biến hoisting trong javascript

Trong Javascript, bạn có thể định nghĩa một biến sau khi sử dụng nhờ tính năng hoisting.

Javascript sẽ di chuyển toàn bộ các khai báo biến lên đầu chương trình. Vì vậy, những dòng code có sử dụng biến mà chưa khai báo sẽ không bị lỗi.

// Gán nhưng chưa khai báo biến
domain = 'freetuts.net';

// Kết quả: Domain là freetuts.net
document.write("Domain là: " + domain);

// Khai báo
var domain;

// Kết quả: Domain là freetuts.net
document.write("<br/> Domain là: " + domain);

Nếu trong lúc khởi tạo mà bạn gán giá trị cho biến thì kết quả sẽ khác

// Gán nhưng chưa khai báo biến
domain = 'freetuts.net';

// Kêt quả: Domain là freetuts.net
document.write("Domain là: " + domain);

// Khai báo
var domain = 'techtuts.net';

// kêt quả: Domain là freetuts.net
document.write("<br/> Domain là: " + domain);

Nếu khai báo biến trước khi sử dụng thì ta vẫn có kết quả giống nhau.

// Khai báo
var domain;

// Gán nhưng chưa khai báo biến
domain = 'freetuts.net';

// Kết quả: Domain là freetuts.net
document.write("Domain là: " + domain);

// Kết quả: Domain là freetuts.net
document.write("<br/> Domain là: " + domain);

Trong ví dụ thứ 3 này thì ta đã khai báo biến trước rồi mới sử dụng sau. Điều này tuân thủ theo quy tắc tạo biến rồi mới sử dụng của hầu hết các ngôn ngữ lập trình. Nó giúp chương trình trở nên sáng và logic hơn.

3. Từ khóa let và var trong hoisting

Việc sử dung từ khóa let var để khai báo một biến sẽ có sự khác biệt trong hoisting.

Sử dụng var: Nếu biến chưa gán giá trị thì sẽ trả về undefined.

console.log(counter); // undefined
var counter = 1;

Đoạn mã trên sẽ tương đương với đoạn mã dưới đây.

var counter;

console.log(counter); // undefined
counter = 1;

Sử dụng let: Nếu biến chưa gán giá trị thì sẽ xuất hiện thông báo lỗi Cannot access before initialization.

console.log(counter);
let counter = 1;

Kết quả:

"ReferenceError: Cannot access 'counter' before initialization

Lỗi này muốn nói rằng biến counter đã được định nghĩa trong bộ nhớ heap nhưng chưa được khởi tạo.

4. Hàm hoisting trong javascript

Cũng giống như các biến, công cụ JavaScript cũng lưu trữ các khai báo hàm. Nó sẽ di chuyển các khai báo hàm lên đầu của chương trình.

let x = 20,
    y = 10;

let result = add(x,y);
console.log(result);

function add(a, b){
    return a + b;
}

Trong ví dụ này thì mình đã sử dụng hàm add rồi mới khai báo sau. Tuy nhiên, javascript vẫn không trả về một lỗi nào cả. Lý do là cơ chế hoisting của javascript đã di chuyển các khai báo hàm lên đầu rồi mới thực thi chương trình.

Có nghĩa là đoạn code dưới đây sẽ tương đương:

function add(a, b){
    return a + b;
}

let x = 20,
    y = 10;

let result = add(x,y);
console.log(result);

5. Hoisting trong biểu thức hàm

Biểu thức hàm hay còn gọi là function expressions. Nó là một hàm được khai báo bằng cách gán vào một biến.

var add = function(x, y) {
    return x + y;
}

Hàm add chính là một function expressions.

Quay trở lại bài toán. Câu hỏi là chuyện gì sẽ xảy ra nếu ta sử dụng một function expressions trước rồi mới khai báo sau? Hãy xem ví dụ dưới đây.

let x = 20,
    y = 10;

let result = add(x,y);
console.log(result);

var add = function(x, y) {
    return x + y;
}

Chạy đoạn code này thì kết quả sẽ xuất hiện lỗi:

"TypeError: add is not a function

Lý do rất đơn giản. Javascript sẽ xem biết add là một biến thông thường, nên khi nó đưa lên đầu thì sẽ là một biến chứ không phải là một hàm. Vì vậy, khi sử dụng sẽ xuất hiện lỗi add is not a function.

6. Hoisting trong arrow function

Cú pháp tạo arrow function sẽ như sau:

var function_name = () => bieuthuc;

Chính vì vậy, nếu bạn sử dụng arrow function trước rồi mới khai báo thì sẽ bị lỗi function_name không phải là một hàm.

7. Lời kết

Hoisting nghe có vẻ kì lạ và hay, nhưng riêng cá nhân mình thấy hoisting không thực sự tốt. Bởi theo sự logic của các ngôn ngữ lập trình là bạn phải sử dụng một biến trước khi khai báo chúng. Và Hoisting trong javascript đã phá vỡ đi quy tắc đó.

Cùng chuyên mục:

Functional Programming là gì? Tại sao và khi nào bạn nên sử dụng trong JavaScript

Functional Programming là gì? Tại sao và khi nào bạn nên sử dụng trong JavaScript

Những tính năng mới trong ES6+ trong JavaScript

Những tính năng mới trong ES6+ trong JavaScript

4 cách tránh memory leaks trong JavaScript

4 cách tránh memory leaks trong JavaScript

Capturing và bubbling Event trong Javascript

Capturing và bubbling Event trong Javascript

Phân biệt prototype và __proto__ trong JavaScript

Phân biệt prototype và __proto__ trong JavaScript

Cách hoạt động của Event Loop trong JavaScript

Cách hoạt động của Event Loop trong JavaScript

Phương thức bind(), call(), và apply() trong JavaScript

Phương thức bind(), call(), và apply() trong JavaScript

Cách khắc phục lỗi

Cách khắc phục lỗi "hoisting" trong JavaScript

Sử dụng Promise.all và Promise.race để quản lý các Promise trong JavaScript

Sử dụng Promise.all và Promise.race để quản lý các Promise trong JavaScript

Xử lý bất đồng bộ bằng vòng lặp for-await trong JavaScript

Xử lý bất đồng bộ bằng vòng lặp for-await trong JavaScript

Sự khác biệt giữa Promise, Callback và Async/Await trong JavaScript

Sự khác biệt giữa Promise, Callback và Async/Await trong JavaScript

Cách sử dụng Async functions trong JavaScript

Cách sử dụng Async functions trong JavaScript

Hàm String isspace() trong Python

Hàm String isspace() trong Python

Cách tạo số ngẫu nhiên trong Javascript

Cách tạo số ngẫu nhiên trong Javascript

Hướng dẫn cách tạo một số ngẫu nhiên ...

Cách gộp hai object javascript lại với nhau

Cách gộp hai object javascript lại với nhau

Cách lấy chiều dài của object trong Javascript

Cách lấy chiều dài của object trong Javascript

Hướng dẫn giải phương trình bậc 1 bằng Javascript

Hướng dẫn giải phương trình bậc 1 bằng Javascript

Cách dùng nextSibling trong javascript

Cách dùng nextSibling trong javascript

Cách dùng insertAdjacentHTML trong javascript

Cách dùng insertAdjacentHTML trong javascript

Cách dùng innerHTML trong Javascript

Cách dùng innerHTML trong Javascript

Top