Scope và Hoisting trong JavaScript

11 tháng 3, 2021 By DEVERA ACADEMY

Biến (variable) là phần cơ bản và quan trọng của bất kỳ ngôn ngữ lập trình nào, được sử dụng để lưu trữ các giá trị.


Đối với ngôn ngữ lập trình JavaScript, một biến có thể lưu trữ bất kỳ kiểu giá trị nào. Nó có thể là số, chuỗi, boolean, mảng, đối tượng,... Và cách sử dụng biến trong vô cùng đơn giản:

  • Khai báo một biến

  • Gán một giá trị 

  • Sử dụng


Ví dụ:



Trước ES6, chúng ta sử dụng var làm từ khóa để khai báo biến, nhưng sau ES6 có hai từ khóa mới là let và const. Để hiểu được sự khác biệt giữa let và const so với var, chúng ta cần hiểu được ScopeHoisting.

1. Scope

Scope được hiểu là phạm vi sử dụng của biến, gồm có:

  • Global Scope: biến toàn cục

  • Local Scope: biến cục bộ

Ví dụ:


Output:



ReferenceError là gì?

Trong chương trình trên, gồm có hai biến globallocal.

Biến cục bộ nằm trong hàm doSomething, vì vậy bạn không thể truy cập nó bên ngoài hàm. Có nghĩa là phạm vi sử dụng của biến cục bộ là bên trong hàm.


Biến toàn cục được khai báo bên ngoài hàm, vì vậy bạn có thể truy cập nó từ bất cứ đâu. Do đó, biến toàn cục có thể được sử dụng trong cả chương trình.


Sau ES6, Local scope được chia thành hai loại:

  1. Functional Scope cho var

  2. Block Scope dùng cho letconst


Hãy xem đoạn code dưới đây:

Nếu chúng ta cố gắng truy cập biến letconst bên ngoài if, Output sẽ là một ReferenceError. Tuy nhiên, với biến khai báo bằng var thì cả trong và ngoài if đều có thể thực hiện đúng.

 

2. Hoisting

Khi một biến hoặc một hàm được khai báo, phần khai báo của nó sẽ được chuyển lên đầu tiên.


Để dễ hiểu hơn, đây là ví dụ về Hoisting:

        1. Truy cập một biến trước khi nó được khai báo và khởi tạo



        2. Truy cập một biến trước khi nó được khởi tạo mà chưa thực hiện khai báo

Nếu chúng ta truy cập một biến trước khi nó được khai báo và khởi tạo, nó sẽ trả về undefined. Tuy nhiên, nếu chúng ta truy cập một biến trước khi nó được khởi tạo mà không khai báo, nó sẽ trả về một ReferenceError.


Ở trường hợp thứ hai, chúng ta không khai báo tên trước khi sử dụng biến, vì vậy Output là một ReferenceError. Còn ở trường hợp thứ nhất, JavaScript tự động khai báo tên biến trước khi được sử dụng vì ta khai báo biến bằng từ khóa var.



Một ví dụ khác về Hoisting:

Ta có thể dễ dàng dự đoán rằng kết quả đầu ra phải là true. Nhưng do JavaScript đã khai báo một câu lệnh khởi tạo biến mới ở trên cùng của hàm checkHoisting, do đó output là undefined.


Nhưng trường hợp này hiếm khi xảy ra với let hoặc const vì nó khởi tạo biến Block Scope



Một ví dụ khác:



Bạn có đoán được tại sao Output lại như vậy không?

Vì khi chúng ta khai báo lại một biến với giá trị khác:

  • Trường hợp sử dụng var, do hoisting, giá trị của biến được cập nhật với giá trị mới nhất, do đó kết quả đầu ra là false.

  • Nhưng trong trường hợp letconst, nó sẽ gây ra lỗi cú pháp rằng biến này đã được khai báo. Vậy nên việc trùng lặp tên biến có thể gây ra lỗi.

Kết luận:

Do ScopeHoisting mà việc sử dụng từ khóa var có thể gây ra kết quả không mong muốn, bạn nên cân nhắc sử dụng letconst. Hy vọng bài viết này có thể giúp bạn nắm được cách sử dụng biến trong JavaScript với Scope và Hoisting.



Tác giả: Sarvesh Prajapati

Dịch bởi Devera Academy