ES6 đề cập đến phiên bản 6 của ngôn ngữ lập trình ECMA Script. ECMA Script là tên chuẩn cho JavaScript và phiên bản 6 là phiên bản tiếp theo sau phiên bản 5 được phát hành vào năm 2011. Đây là một cải tiến lớn cho ngôn ngữ JavaScript và thêm nhiều tính năng để giúp việc phát triển phần mềm quy mô lớn dễ dàng hơn
Nhiều tính năng mới được giới thiệu trong ES6 so với ES5. Hiện nay thì nhiều nhà phát triển đã quen với ES6 và bắt đầu sử dụng những tính năng mới đó. Một trong các đặc tính mới của ES6 là bổ sung từ khóa let và const dùng khai báo biến. Câu hỏi là sự khác nhau giữa dùng var (trong ES5) với dùng let và const (trong ES6)?
Var
Trước khi xuất hiện ES6, khai báo biến sử dụng var. Tuy nhiên, có nhiều vấn đề khi khai báo với var. Đó là lý do cần có cách khai báo biến mới trong Javascript. Đầu tiên, chúng ta sẽ tìm hiểu khai báo với var có đặc điểm thế nào.
Phạm vi của var (Scope of var)
Khái niệm phạm vi (scope) nghĩa là xác định vị trí có thể sử dụng biến. Khai báo biến với var được xác định có phạm vi toàn cục (global) hoặc phạm vi cục bộ/ hàm nếu khai báo trong hàm.
Phạm vi toàn cục nếu khai báo biến nằm ngoài khai báo một hàm. Nghĩa một biến khi khi báo bên ngoài khối khai báo hàm có thể dùng trong toàn bộ window. Biến được khai báo trong hàm thì chỉ có thể truy cập ở trong khối khai báo của hàm.
Để hiểu rõ hơn, xem xét ví dụ:
var greeter = “hey hi”;
function newFunction() {
var hello = “hello”;
}
Trong đó, biến greeter có phạm vi toàn cục, biến hello có phạm vi cục bộ hay hàm. Vì thế, biến hello không thể được truy cập ngoài hàm newFunction.
var tester = “hey hi”;
function newFunction() {
var hello = “hello”;
}
console.log(hello); // error: hello is not defined
Khi truy cập biến hello sẽ xuất hiện thông báo lỗi hello is not defined
Các biến khai báo với var có thể được tái khai báo và cập nhật
Các biến có thể tái khai báo và cập nhật biến trong cùng phạm vi và sẽ không xuất hiện lỗi. Ví dụ biến greeter được khai báo lại trong cùng phạm vi
var greeter = “hey hi”;
var greeter = “say Hello instead”;
Tương tự như
var greeter = “hey hi”;
greeter = “say Hello instead”;
Hàm vi ngầm định khi khai báo biến với var
Hành vi ngầm định của Javascript khi khai báo biên với var là chuyển vị trí khai báo biến hay khai báo hàm lên đầu của phạm vi trước khi thực hiện mã. Nghĩa là chúng ta có thể thực hiện được với ví dụ:
console.log (greeter);
var greeter = “say hello”
Đoạn mã sẽ được điều chỉnh như sau:
var greeter;
console.log(greeter); // greeter is undefined
greeter = “say hello”
Khai báo biến greeter sẽ được đưa lên đầu và khởi tạo với giá trị undefined
Vấn đề với var
Vấn đề được giải thích thông qua ví dụ:
var greeter = “hey hi”;
var times = 4;
if (times > 3) {
var greeter = “say Hello instead”;
}
console.log(greeter) // “say Hello instead”
Vì biểu thức times > 3 trả về true, greeter được định nghĩa lại và gán giá trị “say Hello instead”. Điều này không phải vấn đề nếu chúng ta muốn định nghĩa lại biến greeter và trong trường hợp ngược lại, khi biến greeter đã xuất hiện trước đó và chúng ta không nhận ra đã định nghĩa lại biến greeter.
Nếu biến greeter được sử dụng ở trong các phần khác của mã sau khi được định nghĩa lại, kết quả nhận được sẽ rất ngạc nhiên. Điều này có thể gây ra lỗi trong mã Javascript và đó là lý do let và const được giới thiệu
Let
Hiện nay, let được yêu thích khi khai báo biến. Let là sự cải tiến của khai báo dùng var và có thể giải quyết vấn đề gặp phải của var.
Let được định phạm vi trong khối mã (Block-scoped)
Một khối là một đoạn mã được bao bởi cặp dấu mở ngoặc nhọn và đóng ngoặc nhọn { }. Mọi lệnh trong cặp dấu là một khối mã (Block)
Biến khai báo với let trong khối mã chỉ có thể dùng trong khối mã đó. Ví dụ:
let greeting = “say Hi”;
let times = 4;
if (times > 3) {
let hello = “say Hello instead”;
console.log(hello);// “say Hello instead”
}
console.log(hello) // hello is not defined
Khi truy cập biến hello bên ngoài khối mã chứa khai báo sẽ nhận được thông báo hello is not define. Bởi vì biến hello được khai báo bằng let và chỉ tồn tại trong khối mã của mệnh đề if.
Let có thể được cập nhật nhưng không được khai báo lại
Giống với khai báo dùng var, biến khai báo với let có thể được cập nhật trong phạm vi tồn tại. Nhưng không giống với var, biến let không thể khai báo lại trong phạm vi tồn tại. Ví dụ:
let greeting = “say Hi”;
greeting = “say Hello instead”;
Biến greeting có thể cập nhật nội dung mới là “say Hello instead”. Chương trình sẽ báo lỗi khi thực hiện khai báo lại greeting giống với ví dụ dưới đây:
let greeting = “say Hi”;
let greeting = “say Hello instead”; // error: Identifier ‘greeting’ has already been declared
Tuy nhiên, nếu cùng tên biên được định nghĩa khác phạm vi tồn tại thì sẽ không có lỗi xảy ra:
let greeting = “say Hi”;
if (true) {
let greeting = “say Hello instead”;
console.log(greeting); // “say Hello instead”
}
console.log(greeting); // “say Hi”
Trong ví dụ, biến greeting tồn tại với hai thể hiện ở hai phạm vi khác nhau là toàn cục (Global) và khối mã của if. Vì vậy, sẽ không có lỗi xảy ra ở trường hợp này.
Trong thực tế, dùng let tốt hơn var. Khi dùng let, chúng ta không bận tâm biến có dùng trùng tên với biến khai báo trước đó ở phạm vi tồn tại khác. Điều này, khắc phục được hạn chế của var mà chúng ta đã bàn luận trước đó.
Dịch chuyển khai báo của let
Giống với var, khai báo let sẽ được dịch chuyển lên đầu mã. Nhưng biến khai báo với var được khởi gán là undefined, với let thì không khởi gán giá trị. Vì thế, khi cố dùng biến let với trước khi khai báo biến sẽ nhận được lỗi tham chiếu (Reference error)
Const
Biến được khai báo với const chứa giá trị hằng (Giá trị không thể thay đổi trong khi thực hiện). Khai báo const chia sẽ tính tương đồng với khai báo let.
Khai báo const được định phạm vi theo khối mã (Block-scoped)
Giống với khai báo let, khai báo biến const chỉ được truy cập trong khối mã biến được khai báo
Const không thể được cập nhật và khai báo lại
Không thể cập nhật và khai báo lại nghĩa là giá trị của biên không thể được thay đổi và không thể khai báo biến có trùng tên trong cùng phạm vi tồn tại
Ví dụ:
const greeting = “say Hi”;
greeting = “say Hello instead”;// error: Assignment to constant variable.
Khi thay đổi giá trị của biến greeting sẽ nhận được lỗi
Ví dụ về khai báo lại biến:
const greeting = “say Hi”;
const greeting = “say Hello instead”;// error: Identifier ‘greeting’ has already been declared
Biến greeting được khai báo lại và sẽ có lỗi xảy ra.
Mọi biến được khai báo với const, phải được khởi tạo giá trị lúc khai báo
Hành vi của biến const hơi khác khi áp dụng với các đối tượng. Trong khi đối tượng thì không thể thay đổi hay cập nhật, thuộc tính của đối tượng thì có thể. Ví khai báo đối tượng const:
const greeting = {
message: “say Hi”,
times: 4
}
Không thể đối giá trị của biên greeting giống như:
greeting = {
words: “Hello”,
number: “five”
} // error: Assignment to constant variable.
Nhưng có thể thay đổi giá trị của thuộc tính message:
greeting.message = “say Hello instead”;
Dịch chuyển với khai báo const
Giống với let, khai báo const được dịch chuyển lên đầu của đoạn mã nhưng không được khởi gán giá trị.
Tóm lại, sự khác nhau giữa var, let, const có thể được tóm lược như sau:
- Khai báo var được định phạm vi toàn cục (global) hay hàm (function) trong khi let và const được định phạm vi là khối mã (block)
- Biến var có thể được cập nhật và khai báo lại trong phạm vi tồn tại; biến let có thể được cập nhật nhưng không thể khai báo lại; biến const không thể cập nhật nhưng không thể khai báo lại.
- Khai báo của var, let, const đều được dịch chuyển lên đầu của phạm vi. Nhưng trong khi biến var được khởi gán giá trị với undefined, biến let và const không được khởi gán giá trị.
- Trong khi var và let có thể được khai báo không khởi gán giá trị, const phải khởi gán giá trị khi khai báo.
Thầy Nguyễn Ngọc Anh – Bộ môn CNTT – FPT Mạng cá cược bóng đá Đà Nẵng Biên soạn.