Phạm vi biến trong JavaScript

Ngày đăng: 02/10/2020   -    Cập nhật: 02/10/2020


Một trong những điều khiến chuyên gia lập trình JavaScript khác biệt người mới học là ở việc họ nắm rõ phạm vi biến trong JavaScript. Vì thế, hôm nay chúng ta sẽ tìm hiểu về Variable Scope (Phạm vi biến).

Hi vọng là bạn sẽ nắm bắt được để nắm giữ chương trình JS tốt hơn.


Phạm vi biến trong JavaScript

Phạm vi biến trong JavaScript

1. Phạm vi biến là gì?


Phạm vi biếnkhả năng truy cập của biến, objectfunction trong JavaScript.

Như các bạn đã biết thì biến sẽ được khai báo mọi nơi trong JavaScript. Nhưng tùy theo việc chúng được khai báo ở đâu thì sẽ có phạm vi khác nhau.

Có hai loại phạm vi của biến trong JavaScript:


  • Pham vi cục bộ (local scope)
  • Toàn cục (global scope)

2. Biến toàn cục (Global Variable)


Khi một biến được định nghĩa bên ngoài bất cứ một function nào thì nó sẽ có giá trị là toàn cục (global), được sử dụng ở mọi nơi trong chương trình.

Nhưng vấn đề nó lại không đơn giản bởi vì sự có mặt / vắng mặt của từ khóa :D

Nếu chúng ta khai báo biến trong functionkhông có từ khóa thì sẽ trở thành biến global.

Để mình ví dụ:



var hoTen = "Ngô Trung";

function changeName() {
  // Khai báo biến trong function
  // mà không có từ khóa var
  hoTen = "Nguyễn Văn A";
}

function showName() {
  console.log(hoTen);
}

console.log(hoTen); // Ngô Trung

// Thay đổi hoTen
changeName();
showName(); // Nguyễn Văn A
 

Với đoạn code trên:

  • Biến hoTen sẽ truy cập được bất cứ đâu trong chương trình.
  • Khi ta sử dụng hàm changeName() thì giá trị trong biến hoTen sẽ thay đổi theo – có nghĩa là biến này truy cập được trong hàm.

Một ví dụ khác khi khai báo biến trong hàm không có từ khóa:


// Tạo hàm tính tổng hai số a và b
function tongHaiSo(ab) {
    // Khai báo biến trong hàm
    // mà không có từ khóa var
    tong = a + b;
    return tong;
}

var ketqua = tongHaiSo(56);
console.log(ketqua); // Kết quả: 11
console.log(tong); // Kết quả: 11
 

Cả hai đều cho ra kết quả là 11:

  • Trong một hàm để tạo một biến global (hoặc gọi là có phạm vi toàn cục - global scope) chỉ cần không khai báo với từ khóa var (không sử dụng từ khóa)
  • Biến tong không có từ khóa var có thể truy cập được ở bên ngoài phạm vi của hàm tongHaiSo(a, b) như vậy biến tongbiến global.

Và giờ ta thử sử dụng từ khóa var để khai báo biến bên trong hàm xem nhé.

Sử dụng lại chương trình bên trên:


 
// Tạo hàm tính tổng hai số a và b
function tongHaiSo(ab) {
    // Khai báo biến trong hàm
    // mà không có từ khóa var
    var tong = a + b;
    return tong;
}

var ketqua = tongHaiSo(56);
console.log(ketqua); // Kết quả: 11
console.log(tong); // Kết quả: error: Uncaught ReferenceError: tong is not defined
 

Biến tong bây giờ đã được giới hạn lại phạm vi chỉ trong hàm tongHaiSo. Do đó cố tình gọi sẽ trả về lỗi như trên.

3. Biến cục bộ (Local Variable)


Một biến cục bộ (local variable) là biến được giới hạn trong phạm vi (scope) nhất định như: Trong một hàm, trong vòng lặp, ...

Một biến cục bộ được định nghĩa trong hàm với từ khóa sẽ là biến cục bộ . Nếu các bạn định nghĩa không có từ khóa var thì sẽ trở thành biến toàn cục.

Biến cục bộ sẽ không được truy cập ở bất cứ đâu ngoài hàm mà nó được định nghĩa.

Sử dụng lại ví dụ trên (chỉ viết để bạn nhìn rõ hơn):



// Tạo hàm tính tổng hai số a và b
function tongHaiSo(ab) {
    // Khai báo biến cục bộ
    var tong;
    tong = a + b;
    return tong;
}
 

Sau đó, ta gọi:


var ketqua = tongHaiSo(56);
console.log(ketqua); // Kết quả: 11
console.log(tong); // Kết quả: error: Uncaught ReferenceError: tong is not defined
 

Như vậy, biến tong đã bị giới hạn phạm vi.

Chúng ta không thể gọi nó từ global nữa.

Vì thế, đó chính là biến cục bộ.


4. Một số vấn đề hay nhầm lẫn khi sử dụng biến

 

4.1. Tên biến cục bộ trùng tên với biến toàn cục


Vấn đề tên biến là một vấn đề "TO LỚN" trong lập trình. Trong JavaScript thì vấn đề này càng to hơn nữa.

Vì khi lập trình, chúng ta sẽ phải đặt tên biến, tên hàm, tên .... rất nhiều.


> Trong Java thì bạn sẽ không gặp vấn đề này bởi vì tính chặt chẽ của nó. Tham khảo ngay KHÓA HỌC JAVA WEB (Full stack) nếu bạn yêu thích tính chặt chẽ của ngôn ngữ lập trình.

Do đó, chúng ta sẽ có khả năng viết một hàm mà trong đó có tên biến (biến cục bộ) trùng với biến của chương trình chính (biến toàn cục).

Ví dụ:



// Khai báo biến toàn cục
var tong = 12;

function tongHaiSo(ab) {
    // Khai báo biến cục bộ
    var tong;
    tong = a + b;
    return tong;
}

var ketqua = tongHaiSo(56);
console.log(ketqua); // Kết quả: 11
console.log(tong); // Kết quả: 12
 

Khi ta tạo một biến tong toàn cục tong có giá trị là 12

Trong hàm tongHaiSo(a, b) ta cố tình tạo một biến tong và gán cho nó là a + b.

Như vậy khi gọi tongHaiSo(5, 6) thì biến tong toàn cục sẽ bị không thay đổi giá trị.


Trong JavaScript việc trùng tên hoàn toàn không gây ra lỗi chương trình.

Nhưng nó gây ra sự nhầm lẫn.

Chương trình đơn giản còn dễ nhìn, chương trình phức tạp thì mỏi mắt tìm bug luôn.


4.2. Từ khóa let và var


Ở bài biến trong JavaScript mình đã nói cơ bản về hai từ khóa letvar này, mình sẽ nói cụ thể hơn nhé.

Cụ thể let cho phép tạo ra biến có phạm vi trong một khối { } , còn var thì không.

Ví dụ:



// Tạo ra một biến toàn cục
var hoTen = "Ngô Trung";

function changeName() {
    if (true) {
        var hoTen = "Nguyễn Văn A";
    }
    console.log(hoTen);
}

changeName(); // Kết quả: Nguyễn Văn A
console.log(hoTen); // Kết quả: Ngô Trung
 

Trong ví dụ này, ở trong hàm changeName() thì ta sử dụng một câu lệnh if (Chủ yếu để tạo ra một khối code mà thôi).

Ta khai báo var hoTen = "Nguyễn Văn A"; trong câu lệnh if này.

Lúc này, câu lệnh console.log(hoTen); nằm trong hàm changeName(), nằm ngoài hàm if lại có thể truy cập đến biến hoTen.

Điều này có nghĩa là gì?

Có nghĩa là biến hoTen này có phạm vi là phạm vi hàm.

OK.

Bây giờ mới khó đây này.

Giả sử hàm của bạn không đơn giản như vậy mà khá là phức tạp.

Nhỡ đâu đó bạn lại khai báo thêm một biến hoTen trong hàm changeName() nữa thì vấn đề gì sẽ xảy ra?



// Tạo ra một biến toàn cục
var hoTen = "Ngô Trung";

function changeName() {
    if (true) {
        var hoTen = "Nguyễn Văn A";
    }

    // Tạo một block code
    {
        var hoTen = "Nguyễn Văn B";
    }
    console.log(hoTen);
}

changeName(); // Kết quả: Nguyễn Văn B
console.log(hoTen); // Kết quả: Ngô Trung
 

Việc khai báo như vậy hoàn toàn không làm lỗi chương trình.

Nhưng lúc này, việc nhầm lẫn sẽ xảy ra.

Câu lệnh console.log(hoTen); mà bạn viết ý định truy cập đến biến nào đây???

* Cả vấn đề hoisting nữa. (Nhưng bạn sẽ được tìm hiểu nó sau)

Do đó, trong phiên bản ES2015 thì JavaScript có thêm từ khóa let để giải quyết vấn đề này.

Ở ví dụ bên trên, chúng ta thay từ khóa var bằng từ khóa let



// Tạo ra một biến toàn cục
var hoTen = "Ngô Trung";

function changeName() {
    if (true) {
        let hoTen = "Nguyễn Văn A";
    }
    console.log(hoTen);
}

changeName(); // Kết quả: Ngô Trung
console.log(hoTen); // Kết quả: Ngô Trung
 

Như bạn thấy, câu lệnh console.log(hoTen); nằm trong cùng một hàm nhưng không thể truy cập đến.

Bởi vì từ khóa let đã giới hạn các biến mà nó khai báo ở trong phạm vi khối (block scope).

Có nghĩa là nó chỉ có thể truy cập trong phạm vi dấu ngoặc nhọn { } mà nó được khai báo.

Chúng là làm thế này thì được:



// Tạo ra một biến toàn cục
var hoTen = "Ngô Trung";

function changeName() {
    if (true) {
        let hoTen = "Nguyễn Văn A";
        console.log(hoTen);
    }
    
}

changeName(); // Kết quả: Nguyễn Văn A
console.log(hoTen); // Kết quả: Ngô Trung
 

Còn khi ta khai báo biến bằng từ khóa let nhưng mà ở phạm vi toàn cục như thế này:


// Tạo ra một biến toàn cục
let hoTen = "Ngô Trung";

function changeName() {
    if (true) {
        let hoTen = "Nguyễn Văn A";
        console.log(hoTen);
    }
    console.log(hoTen);

}

changeName();
 

Thì kết quả ta sẽ được:


Nguyễn Văn A
Ngô Trung
 

Ngoài một hàm bạn cũng không thể truy cập đến biến:


{
    let hoTen = "Nguyễn Văn A";
    console.log(hoTen);
}
console.log(hoTen); // Kết quả: Ngô Trung
 

Bạn sẽ nhạn được lỗi là:


error: Uncaught ReferenceError: hoTen is not defined
 

Và một điểm hay nữa của let là nó không cho phép khai báo hai biến cùng tên trong cùng một phạm vi.

Ví dụ như thế này:



// Tạo ra một khối mã
{
    let hoTen = "Ngô Trung";
    // Cố tình khai báo biến cùng tên
    // trong cùng phạm vi
    let hoTen = "NIIT";
}
 

Lúc đó, bạn sẽ nhận được thông báo lỗi ngay lập tức tương tự như thế này.


Indentifier 'hoTen' has already been declared (6:6)
 

Tổng kết


Như vậy bạn hãy dựa vào tình huống, tính chất của công việc mà chọn sử dụng let hay var và sử dụng biến toàn cục hay biến cục bộ để tạo ra phạm vi biến hợp lý trong JavaScript bạn nhé.

Hẹn gặp lại các bạn ở bài học tiếp theo.

Bình luận Facebook
Đăng ký tư vấn
Nhân viên gọi điện tư vấn miễn phí sau khi đăng ký
Được cập nhật các ưu đãi sớm nhất
Hotline: 0383180086
Tên không được để trống
Số điện thoại không được để trống
Email không được để trống
Hãy đăng ký để nhận những thông tin mới nhất về học bổng mới nhất tại NIIT - ICT Hà Nội
top
Đóng lại Đăng ký học tại NIIT - ICT Hà Nội
6260+ học viên đã theo học tại NIIT - ICT Hà Nội và có việc làm tốt trong ngành lập trình. Nắm lấy cơ hội ngay hôm nay!
Chọn khóa học
  • KHÓA HỌC LẬP TRÌNH FRONT END VỚI REACT.JS
  • KHÓA HỌC LẬP TRÌNH PHP WEB
  • Khóa học PHP Full stack [2023] cho người mới bắt đầu
  • Khóa học BIG DATA với Hadoop và Spark
  • Khóa học Lập trình Android tại Hà Nội
  • [Tuyển sinh 2023] Lập trình viên Quốc tế DigiNxt
  • Khóa học Tiền lương & Phúc lợi (C&B Excel) tại Hà Nội
  • LẬP TRÌNH GAME
    • Khóa học Lập trình Game Unity
  • LẬP TRÌNH WEB FRONT END
    • KHÓA HỌC PYTHON HƯỚNG ĐỐI TƯỢNG
    • KHÓA HỌC ANGULAR & TYPESCRIPT (FRONT END)
  • LẬP TRÌNH WEB BACK END
    • LẬP TRÌNH JAVA WEB VỚI FRAME WORK
    • Lập trình Web với Django
    • Lập trình PHP với Laravel Framework
  • CHƯƠNG TRÌNH ĐÀO TẠO ỨNG DỤNG CÔNG NGHỆ
    • Khóa học Tiền lương & Phúc lợi (C&B Excel) tại TP HCM
  • LẬP TRÌNH WEB FULL STACK
    • Khóa học Java Full stack (IJFD)
  • LẬP TRÌNH MOBILE
    • FRONT-END VỚI REACTJS VÀ REACT NATIVE
    • Lập trình Android Nâng cao
  • ĐÀO TẠO CHO DOANH NGHIỆP
    • KHÓA HỌC BUSINESS ANALYSIC TỪ CƠ BẢN ĐẾN NÂNG CAO 2023
    • Khóa học Magento: Làm chủ CMS TMĐT lớn nhất
    • Khóa học IOT: Xây dựng Sản phẩm IOT với Raspberry Pi
    • Khóa học Automation Testing Chuyên nghiệp
  • KHÓA HỌC DỰ ÁN
    • Học sử dụng bộ Office: Word, Excel, Power Point, Mail chuyên nghiệp
  • KHÓA HỌC KHÁC
    • VBA Excel Toàn Tập (Cơ Bản - Nâng Cao)
    • VBA Excel Nâng cao
    • Khóa học JMeter: Performance Testing
    • Khóa học Tester đạt chuẩn Quốc tế ISTQB Foundation Level
    • Khoá Học Tester đạt chuẩn quốc tế ISTQB Advanced Level
Bạn chưa chọn khóa học cần đăng ký
Tên không được để trống
Số điện thoại không được để trống
Email không được để trống
Đăng ký học thành công!
Cảm ơn bạn đã đăng ký học tại NIIT - ICT HÀ NỘI!