+3

Javascript - Phân biệt let, const và var

Giới thiệu

Javascript 2015 (ES6) ra mắt kèm theo rất nhiều tính năng giúp chúng ta viết code một cách gọn gàng, sạch đẹp hơn, dễ dàng đọc hơn. Một số chức năng tiêu biểu như: let, const, arrow function, promises, ... Trong bài viết này chúng ta sẽ tìm hiểu về letconst phục vụ trong việc khai báo dữ liệu trong JS. Sự khác biệt của let, constvar.

Sự khác biệt

Hoisting

Trước tiên ta sẽ tìm hiểu xem hoisting là gì trước khi phân biệt let, constvar. Giải thích một cách dễ hiểu thì hoisting là việc di chuyển các khai báo lên đầu để thục thi code của JS. Vậy let, const, var có hoisting khác nhau như thế nào?. Ta xét ví dụ sau:

// index.js

console.log(foo);
console.log(bar);
console.log(mickey);

var foo = 'Hi';
let bar = 'Hello';
const mickey = 'kimsohyun';

Trong file index.js ta tiến hành log ra giá trị của biến foo, bar, mickey trước khi chúng được khai báo. Khi ta chạy file index.js thì ta sẽ có kết quả như sau.

Trong lần chạy đầu tiên sau khi compiled ta thấy terminal in ra undefined và một lỗi ReferenceError: bar is not defined. Sau đó mình có xóa dòng console.log(bar) đẻ tiến hành chạy lại thì thấy terminal tiếp tục in ra undefined và lõi ReferenceError: mickey is not defined. Qua ví dụ ta dễ dàng nhân thấy varhoisting, let, const không có hoisting, nhưng sự thật không phải như vậy. Tất cả các khai báo(function, let, const, var) trong Javascript đều được hoisted. Sự khác biệt ở đây là var khi hoisting thì được khởi tạo là giá trị undefined còn constlet thì không.

Ta có sau khi hoisting thì var sẽ kiểu như sau.

var foo;

console.log(foo);

foo = 'Hi';

Scope

Scope hiểu một cách đơn giản là phạm vi sử dụng của một biến. Ta xét ví dụ sau:

if (true) {
    var foo = "foo!";
}

console.log(foo);

(function() {
    var bar = "bar!";
})();

console.log(bar);

Output sẽ như sau:

Ta có thể thấy khi compiled thì biến foo được khai báo trong if còn biến bar được khai báo trong một hàm. Ta có kết quả in ra được biến foo nhưng đến bar lại báo một lỗi ReferenceError. Như vậy biến var khi khái báo trong mệnh đề if (block scope) sẽ có scope là global nên ta có thể truy cập vào biến đó ở ngoài của mệnh đề if, còn khi sử dụng trong hàm(function) thì sẽ có scope là function scope/local scope nên khi truy cập vào biến đó ở ngoài sẽ lỗi ta chỉ có thể truy cập vào biến đó ở trong scope đó. Biến let, const khi làm tương tự như ví dụ kia ta có kết quả cả hai trường hợp đều có lỗi. Như vậy ta tiếp tục có kết luận biến let, const sẽ là block scope khi ta tiến hành acess vào biến ở ngoài scope thì sẽ không sử dụng được.

if (true) {
    let foo = "foo!";
    if (true) {
        let foo = "foo! scoped";
        console.log(foo);
    }
}

Output:

foo! scoped

Khi biến được khai báo khác scope nhau ta hoàn toàn có thể để trùng tên khi sử dụng sẽ ưu tiên biến ở scope gần nhất. Ví dụ trên ta có thể làm tương tự với const.

Assignment

Ta xét ví dụ

var foo = 'Hi';
let bar = 'Hello';
const mickey = 'kimsohyun';

var foo = 'Hi 2';
let bar = 'Hello 2';
const mickey = 'kimsohyun 2';

Output:

Qua ví dụ trên ta thấy var có thể tiến hành khai báo lại biến nhưng còn letconst thì ta không thể tiến hành khai báo lại.

Xét tiếp ví dụ:

var foo;
let bar;
console.log(foo, bar);

Output:

undefined undefined

Ta thấy đối với var, let ta có thể tiến hành khai báo mà chưa gán giá trị. Nhưng nếu ta khai báo biến const mà không gán giá trị cho nó thì sao? Sau khi thử ta có kết quả nó sẽ báo một lỗi SyntaxError: Missing initializer in const declaration => Khi khai báo với const ta phải gán giá trị cho nó.

Thêm nữa khi xét biến const ta có thể hiểu nó là hằng số. Nên khi ta cố tình thay đổi bién được khai báo với từ khóa const thì ta sẽ gặp một lỗi TypeError: Assigment to constant varibale. Ta không thể sử dụng toán tử gán (=) tới lần thứ 2 với biến const còn đối với letvar ta có thể sử dụng thoải mái. Các bạn có thể kiểm tra với ví dụ bên dưới bằng cách thay const -> var hoặc let

const foo = 123;

foo = 321;

console.log(foo);

Còn một trường hợp mọi người hay mắc sai làm về const như sau:

const obj = {
    name: 'foo'
};

obj.name = 'bar';
console.log(obj.name);

Khi chạy code ta có thể thấy log ra chữ bar nhưng nhiều người hay nhầm lẫn là lỗi vì gán lần thứ 2 cho biến const. Ta không thể sử dụng toán tử gán thứ 2 với biến là const ở đây ta chỉ gán lại một thuộc tính của obj chứ ta không gán lại obj.

Tổng kết

Sau khi xét qua các ví dụ ta sẽ tổng kết lại sự khác biệt của ba biến let, const, var một chút như sau:

Để hiểu kỹ hơn về nó các bạn nên nghiên cứu kỹ các ví dụ mà mình đưa ra giúp hiểu hơn về let, const, var. Đây là bài viết đầu tiền trong series cùng tìm hiểu về ECMAScript - ES6 của mình mong các bạn ủng hộ.

Tham khảo

https://www.valentinog.com/blog/var/


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.