ES6 block bindings (variables)

Nếu các bạn đã từng lập trình C/C++ chắc các bạn đã quen với việc các biến (variables hay bindings) được tạo ra và có phạm vi sử dụng trong đúng khối lệnh (block). Nhưng trong Javascript thì khác, với phiên bản ES6 (ECMAScript 6) các biến được khởi tạo và phạm vi hoạt động sẽ phụ thuộc vào cách mà bạn khai báo nó với từ khóa var hay let. Với từ khóa mới let trong ES6 sẽ giúp bạn thao tác scope và block một cách dễ dàng và an toàn hơn.

1. Khai báo biến với từ khóa var (Declarations are Hoisted)

Trong Javscript khai báo biến với từ khóa var bạn có thể sử dụng biến trước khi khai báo nó mà không gặp bất cứ lỗi hay cảnh báo (warning) nào cả. Chắc các bạn cũng thắc mắc tại sao lại vậy? Để hiểu được điều này ta cần phải tìm hiểu một từ khóa trong Javascript là 'hoisting'. Hoisting là một hành động mặc định của JavaScript luôn đưa khai báo biến với từ khóa var lên trên đầu của scope hiện tại và bạn có khai báo bao nhiêu lần thì nó cũng tương đương với một lần duy nhất ở trên đầu scope. Để hiểu thêm ta sẽ xét vài ví dụ sau đây:

function test() {
  x = 5; // Assign 5 to x
  console.log(x);
  var x; // Initialize x
  console.log(x);
}
test(); // => 5\n5

Trong ví dụ trên ta có thể thấy mặc dù biễn x được gán giá trị bằng 5 trước khi khai báo nó. Đoạn code này vẫn chạy bình thường và in ra x trong 2 lần với giá trị như nhau là 5.

Như vậy đoạn code trên hoàn toàn tương đương với đoạn code sau

function test() {
  var x; // Initialize x
  x = 5; // Assign 5 to x
  console.log(x);
  console.log(x);
}
test(); // => 5\n 5

Ta xét một ví dụ khác

function test() {
  var x = 5; // Initialize x
  console.log(x);
  console.log(y)
  var y = 7; // Initialize y
}
test() // => 5\n undefined

Nhìn vào ví dụ trên hẳn có bạn sẽ nghĩ ràng sẽ in ra 2 giá trị là 5 và 7 tương ứng với x và y. Tuy nhiên bạn cần hiểu rõ Javascript hoisting chỉ đưa khai báo lên trên đầu scope chứ không bao gồm cả phần khởi tạo. Như vậy đoạn code trên sẽ tương ứng với đoạn code sau

function test() {
  var x;
  var y;
  x = 5; // Initialize x
  console.log(x);
  console.log(y)
  y = 7; // Initialize y
}
test() // => 5\n undefined

Phạm vi của biến (scope) khi khai báo với từ khóa var trong javascript có khác so với C/C++ nó không phải gói gọn trong khối lệnh (block), mà phạm vi của nó là function. Nghĩa là bạn khai báo biến ở bất cứ đâu trong block thì ở phần thân function chứ block đó đều dùng được.

  function test(condition) {
    if (condition) {
      var result = "blue";
    } else {
      // can access result here with value is undefined
    }
    console.log(result);
  }
  test(true) // => blue
  test(false) // => undefined

Như bạn có thể thấy mặc dù biến test được khai báo khi mà parameter condition có giá trị là true nhưng nó vẫn có thể được truy cập ở bên ngoài khối lệnh này. Như vậy đoạn code trên hoàn toàn tương đương với

  function test(condition) {
    var result;
    if (condition) {
      result = "blue";
    } else {
      // can access result here with value is undefined
    }
    console.log(result);
  }
  test(true) // => blue
  test(false) // => undefined

Với đoạn code này bạn hoàn toàn có thể hiểu được ngay Javascript không báo lỗi là chưa định nghĩa biến result.

Vậy khai báo biến với từ khóa let trong ES6 có gì khác biệt. Chúng ta cùng tìm hiểu ngay sau đây

2. Khai báo với từ khóa let

Về cơ bản thì cú pháp let khá giống với var. Có một điểm khác biệt lớn nhất là khai báo biến với let không hoisted, có nghĩa là phạm vi của biến chỉ trong block mà nó được khai báo và phải khai báo trước khi sử dụng. Để hiểu rõ hơn ta có ví dụ sau

function test(condition) {
  if (condition) {
    let result = "blue";
    console.log(result);
  } else {
    // can't access result here
    console.log(result); // will raise errors
  }
  // can't access result here
}
test(true) // => blue
test(false) // => will raise errors

Qua ví dụ trên ta thấy việc khai báo biến với từ khóa let thì phạm vi hoạt động của biến giống với C/C++, phạm vi của nó là block lệnh chứ không phải là scope như var. Cũng tương tự khi khai báo biến trong vòng lặp ....

for(let i = 0; i < 10; i++) {
  console.log(i);
}
// // can't access i here

Khác với var bạn có thể khai báo biến trùng tên bao nhiêu lần tùy thích. Khi sử dụng let là bạn không thể khai báo biến 2 lần với cùng một tên. Nếu bạn khai báo 2 biến trùng một tên sẽ raise ra lỗi. Ta cùng xem một vài ví dụ cho trường hợp này

function test() {
  var a = 1;
  let a = 1; // raise error here
}
function test() {
  let a = 1;
  let a = 1; // raise error here
}
function test() {
  let a = 1; // raise error here
  var a = 2;
}

Qua các ví dụ trên, ta thấy việc khai báo biến với từ khóa let các biến có phạm vi hoạt động rõ ràng do không sử dụng cơ chế hoisting. Hơn nữa với let ta cần tuân thủ nguyên tắc cần khai báo biến trước khi sử dụng và chỉ được khai báo duy nhất một lần cho một biến trong cùng block như vậy sẽ an toàn hơn rất nhiều.Vì vậy nếu bạn dùng ES6 thì cũng được khuyến cáo là nên dùng let thay thế cho var như vậy code của bạn sẽ chạy một cách sáng sủa và an toàn hơn rất nhiều.

Hi vọng qua bài viết bạn sẽ hiểu thêm về 2 cách khai báo biết với letvar trong ES6. Cảm ơn đã theo dõi bài viết!


All Rights Reserved