Trong JavaScript, từ khóa let
được sử dụng để khai báo biến cục bộ có phạm vi (scope) cụ thể trong khối code hoặc hàm. let
đã được giới thiệu trong phiên bản ES6 (ECMAScript 2015) và trở thành một cách phổ biến để khai báo biến trong lập trình JavaScript.
Dưới đây là một số điểm quan trọng về let
và const
,nó thường được ưa chuộng hơn trong lập trình hiện đại vì chúng tạo ra các biến có phạm vi cục bộ, không cho phép khai báo lại, không hoisted, và không liên kết với this
. var
có thể gây ra nhiều vấn đề khó kiểm tra và khó hiểu hơn trong code JavaScript.
- Phạm vi (Scope):
var
: Có phạm vi chức năng (function scope).let
vàconst
: Có phạm vi khối (block scope), nghĩa là chúng chỉ có thể truy cập trong phạm vi của khối code (ví dụ: khốiif
,for
, hoặc hàm).
- Khai báo lại (Redeclare):
var
: Cho phép khai báo lại biến trong cùng một phạm vi.let
vàconst
: Không cho phép khai báo lại biến trong cùng một phạm vi.
- Gán lại giá trị (Reassign):
var
: Cho phép gán lại giá trị cho biến.let
vàconst
: Không cho phép gán lại giá trị cho biến sau khi đã được khai báo (tuy nhiên, vớiconst
, bạn không thể thay đổi giá trị của nó, nhưng nếu biến là một đối tượng, bạn có thể thay đổi thuộc tính của đối tượng đó).
- Tạo biến trước (Hoisted):
var
: Biến được “tạo trước” (hoisted), nghĩa là bạn có thể truy cập biến trước khi nó được khai báo, nhưng giá trị của nó sẽ làundefined
cho đến khi nó được gán giá trị.let
vàconst
: Không được “tạo trước,” nghĩa là bạn không thể truy cập biến trước khi nó được khai báo, và bạn sẽ nhận được lỗi nếu cố gắng làm điều này.
- Liên kết với
this
(Binds this):var
: Liên kết vớithis
(đối tượng gọi hàm) trong hàm.let
vàconst
: Không liên kết vớithis
trong hàm.
Biến được định nghĩa bằng từ khóa let
không thể được khai báo lại.
Điều này có nghĩa là bạn không thể tình cờ khai báo lại một biến đã được khai báo với let
. Với let
, bạn không thể làm như sau:
let x = "John Doe";
let x = 0; // Lỗi SyntaxError: Identifier 'x' has already been declared
Trong ví dụ này, việc khai báo lại biến x
với let
dẫn đến lỗi SyntaxError vì bạn không thể khai báo lại một biến đã tồn tại.
Tuy nhiên, với từ khóa var
, bạn có thể làm như sau:
var x = "John Doe";
var x = 0; // Không có lỗi, x được ghi đè bởi giá trị mới
Với var
, việc khai báo lại biến x
là hợp lệ và biến x
sẽ được ghi đè bởi giá trị mới. Điều này có thể gây ra sự hiểu lầm và xung đột trong code của bạn, nên nên sử dụng let
hoặc const
để tránh việc khai báo lại biến một cách không cần thiết.
Khi sử dụng từ khóa var
, việc khai báo lại một biến có thể gây ra các vấn đề và dẫn đến kết quả không mong muốn.
Khi bạn sử dụng var
để khai báo lại biến x
bên trong khối {}
, nó cũng làm cho biến x
bên ngoài khối đó bị khai báo lại với giá trị mới. Điều này có thể dẫn đến sự hiểu lầm và xung đột trong code của bạn, và đôi khi gây ra lỗi không mong muốn.
var x = 10;
// Ở đây x là 10
{
var x = 2;
// Ở đây x là 2
}
// Ở đây x vẫn là 2
Ví dụ với HTML.
<html>
<body>
<p id="demo"></p>
<script>
var x = 10;
// Here x is 10
{
var x = 2;
// Here x is 2
}
// Here x is 2
document.getElementById("demo").innerHTML = x;
</script>
</body>
</html>
Kết quả.
2
Để tránh vấn đề này và có tính nhất quán hơn trong việc quản lý biến, bạn nên sử dụng từ khóa let
hoặc const
thay vì var
, vì chúng có phạm vi khối (block scope) và không gây ra tình trạng khai báo lại biến ở mức phạm vi chức năng (function scope) như var
.
<html>
<body>
<p id="demo"></p>
<script>
let x = 10;
// Here x is 10
{
let x = 2;
// Here x is 2
}
// Here x is 10
document.getElementById("demo").innerHTML = x;
</script>
</body>
</html>
Kết quả.
10
Điều này làm cho let
và const
trở nên hữu ích trong việc quản lý phạm vi biến và giúp tránh được xung đột và lỗi không mong muốn khi sử dụng biến trong code của bạn.
Khai báo lại một biến JavaScript với từ khóa var
được cho phép bất kỳ đâu trong một chương trình. Điều này có nghĩa bạn có thể khai báo lại biến có cùng tên trong cùng phạm vi hoặc ở bất kỳ đâu trong chương trình. Tuy nhiên, lưu ý rằng việc khai báo lại biến có thể gây ra sự hiểu nhầm và khó debug, và thường không được khuyến nghị trong code chương trình sạch sẽ và dễ đọc.
<html>
<body>
<p id="demo"></p>
<script>
var x = 2;
// Now x is 2
var x = 3;
// Now x is 3
document.getElementById("demo").innerHTML = x;
</script>
</body>
</html>
Trong ví dụ này, biến x
đã được khai báo lại và giá trị của nó đã thay đổi thành 3. Điều này là một tính năng của var
, nhưng cũng có thể gây ra sự hiểu nhầm và lỗi trong code lớn hơn. Kết quả sẽ là 3 như dưới.
3
với let
, bạn không thể khai báo lại một biến có cùng tên trong cùng một khối (block scope). Điều này là một điểm khác biệt quan trọng so với var
, và nó giúp tránh sự hiểu nhầm và xung đột trong code.
var x = 2; // Được phép
let x = 3; // Không được phép (lỗi)
{
let x = 2; // Được phép
let x = 3; // Không được phép (lỗi)
}
{
let x = 2; // Được phép
var x = 3; // Không được phép (lỗi)
}
Trong các ví dụ không được phép, việc khai báo lại biến x
trong cùng một khối (block) dẫn đến lỗi. Điều này giúp đảm bảo tính toàn vẹn của phạm vi và tránh sự hiểu nhầm khi làm việc với các biến cùng tên trong cùng một phạm vi.
Khi sử dụng từ khóa let
, bạn có thể khai báo lại một biến trong một khối khác mà không gây ra lỗi.
<html>
<body>
<p id="demo"></p>
<script>
let x = 2; // Allowed
{
let x = 3; // Allowed
}
{
let x = 4; // Allowed
}
document.getElementById("demo").innerHTML = x;
</script>
</body>
</html>
Kết quả.
2
Khi bạn sử dụng let
để khai báo biến x
trong các khối khác nhau, chúng có phạm vi khối (block scope) riêng biệt. Điều này có nghĩa rằng biến x
trong mỗi khối không ảnh hưởng đến biến x
trong các khối khác, và việc khai báo lại biến x
trong các khối khác nhau hoàn toàn hợp lệ. Điều này giúp bạn quản lý biến một cách linh hoạt và tránh xung đột tên biến trong code của bạn.
Biến được định nghĩa bằng từ khóa var
sẽ được đưa lên đầu của phạm vi chức năng (function scope) hoặc phạm vi toàn cục của tài liệu và có thể được khởi tạo (gán giá trị) bất kỳ lúc nào.
Điều này có nghĩa rằng bạn có thể sử dụng biến trước khi nó được khai báo:
<html>
<body>
<p id="demo"></p>
<script>
carName = "Volvo";
document.getElementById("demo").innerHTML = carName;
var carName;
</script>
</body>
</html>
Kết quả.
Volvo
Trong ví dụ này, biến carName
được gán giá trị “Volvo” trước khi nó được khai báo. JavaScript sẽ tự động đưa biến carName
lên đầu phạm vi và sau đó gán giá trị cho nó. Tuy nhiên, việc này có thể dẫn đến sự hiểu lầm và làm tăng nguy cơ xảy ra lỗi trong code, vì vậy nên tránh sử dụng var
và thay thế bằng let
hoặc const
để có code sạch hơn và dễ đọc hơn.
Biến được định nghĩa bằng từ khóa let
cũng sẽ được đưa lên đầu của khối (block scope) nhưng không được khởi tạo (gán giá trị) bất kỳ lúc nào.
Điều này có nghĩa là sử dụng biến let
trước khi nó được khai báo sẽ dẫn đến lỗi ReferenceError:
carName = "Saab"; // Lỗi ReferenceError: Cannot access 'carName' before initialization
let carName = "Volvo";
Ví dụ với HTML.
<html>
<body>
<p id="demo"></p>
<script>
try {
carName = "Saab";
let carName = "Volvo";
}
catch(err) {
document.getElementById("demo").innerHTML = err;
}
</script>
</body>
</html>
Kết quả.
ReferenceError: Cannot access 'carName' before initialization
Trong ví dụ này, việc sử dụng biến carName
trước khi nó được khai báo với từ khóa let
gây ra lỗi ReferenceError vì biến carName
không được khởi tạo trước đó. Điều này là một tính năng quan trọng của let
, giúp bạn tránh được các lỗi thời gian chạy và đảm bảo tính nhất quán trong code của bạn.
Sự khác nhau giữa var, let và const.
let
và const
thường được ưa chuộng hơn var
trong lập trình hiện đại vì chúng cung cấp tính năng phạm vi khối (block scope) an toàn hơn và loại bỏ một số vấn đề liên quan đến var
. const
được sử dụng khi bạn muốn khai báo một biến không thể thay đổi sau khi được gán giá trị ban đầu. Bảng so sánh giữa var
, let
, và const
dựa trên một số tính năng quan trọng:
- Scope (Phạm vi):
var
: Có phạm vi toàn cục hoặc phạm vi hàm (function scope). Không có phạm vi khối (block scope).let
vàconst
: Có phạm vi khối (block scope), nghĩa là biến chỉ có hiệu lực trong khối code mà nó được khai báo.
- Redeclare (Khai báo lại):
var
: Không bị cản trở khi bạn khai báo lại biến với cùng tên trong cùng phạm vi.let
vàconst
: Không cho phép bạn khai báo lại biến với cùng tên trong cùng phạm vi.
- Reassign (Gán lại giá trị):
var
: Cho phép bạn gán lại giá trị cho biến mà không có ràng buộc nào.let
: Cho phép bạn gán lại giá trị cho biến.const
: Không cho phép bạn gán lại giá trị cho biến sau khi nó đã được gán một giá trị ban đầu. Biếnconst
không thể thay đổi giá trị sau khi đã được gán.
- Hoisted (Nâng lên):
var
: Biến được nâng lên đầu phạm vi của nó (hoisted), nghĩa là bạn có thể truy cập biến trước khi nó được khai báo trong code (tuy nhiên, giá trị sẽ làundefined
).let
vàconst
: Khai báo vớilet
vàconst
cũng được nâng lên, nhưng không thể truy cập biến trước khi nó được khai báo trong code.
- Binds this (Liên kết this):
var
: Liên kết với đối tượng global hoặc đối tượng hàm (function object).let
vàconst
: Không liên kết với đối tượng global hoặc đối tượng hàm. Điều này có nghĩa rằng chúng không thay đổi giá trị củathis
trong các hàm, điều này có thể làm giảm thiểu sự hiểu nhầm và lỗi trong code.
Hỗ trợ trình duyệt.
Thông tin về sự hỗ trợ của các từ khóa let
và const
trong các trình duyệt:
- Chrome 49 (Ra mắt vào tháng 3 năm 2016)
- Edge 12 (Ra mắt vào tháng 7 năm 2015)
- Firefox 36 (Ra mắt vào tháng 1 năm 2015)
- Safari 11 (Ra mắt vào tháng 9 năm 2017)
- Opera 36 (Ra mắt vào tháng 3 năm 2016)
Các phiên bản trình duyệt này hoàn toàn hỗ trợ các từ khóa let
và const
. Tuy nhiên, các phiên bản trình duyệt cũ hơn như Internet Explorer 11 và các phiên bản trình duyệt lỗi thời khác không hỗ trợ hoàn toàn các từ khóa này. Do đó, khi phát triển ứng dụng web, bạn cần xem xét mức hỗ trợ của trình duyệt và có thể cần sử dụng các biện pháp thay thế hoặc polyfill để đảm bảo khả năng tương thích trình duyệt.