Hiểu về Scope trong Javascript



  • Scope là gì ?

    Scope là 1 khái niệm nhằm xác định phạm vi hoạt động của biến.

    Có 1 nguyên tắc trong lập trình đó là giới hạn phạm vi hoạt động của biến xuống càng bé càng tốt. Tại sao phải như vậy :

    • Giả sử bạn có 1 biến x với phạm vi hoạt động rộng cả 3 thành phần A, B , C trong đoạn code của bạn đều có khả năng tác động đến biến x. Khi có lỗi xảy ra biến đó không mang giá trị như bạn mong muốn , sẽ rất khó để biết nguyên nhân là do đâu. Ai là người đã gây phát sinh lỗi ?
    • Bây giờ cũng ví dụ như trên nhưng chỉ có A là tác động được vào biến x. Bạn sẽ quy ngay được trách nhiệm thuộc về ai.

    Scope trong Javascript

    Trong Javascript có 2 loại scope là :

    • Global Scope
    • Local Scope

    Biến được định nghĩa bên trong 1 function sẽ thuộc về Local Scope .
    - Ngược lại :
    Biến được định nghĩa bên ngoài function sẽ thuộc về Global Scope

    Global Scope

    // Scope mặc định là global khi khai báo 1 biến bên ngoài function
    var name = 'Hammad';
    

    Biến thuộc Global Scope có thể được sử dụng và thay thế ở bất cứ đâu.

    var name = 'Hammad'; // biến name thuộc Global Scope
    
    console.log(name); // in ra 'Hammad'
    
    function logName() {
        console.log(name); // biến name có thể được truy cập ở bất cứ đâu
    }
    
    logName(); // in ra 'Hammad'
    

    Chú ý : biến được định nghĩa mà không sử dụng từ khóa khai báo thì được mặc định thuộc vào Global Scope

    function logName() {
      name = "Hammad"; //biến name được mặc định thuộc global scope mặc dù định nghĩa bên trong 1 function
    }
    logName();
    console.log(name); // in ra 'Hammad'
    

    Local Scope

    Các biến được định nghĩa bên trong function thuộc về local scope. Mỗi function khi gọi sẽ tạo ra 1 scope mới. Các function khác nhau sẽ tạo ra các scope khác nhau.

    function one() {
        // Local Scope #1
        var a = 2; //biến a được khai báo trong local scope 1
        function two() {
             // Local Scope #2
            console.log(a) // vì local scope 2 nằm bên trong local scope 1 nên có thể gọi a ở đây       
        }
        two();
    }
    
    function three() {
        // Local Scope #3
        console.log(a) // không thể gọi a ở đây vì local scope 3 và 1 là 2 local scope riêng biệt.
    }
    one(); // in ra 2
    three(); // lỗi
    

    Điều này dẫn đến có thể khai báo biến trùng tên ở các function khác nhau.

    function one() {
        // Local Scope #1
        let a = 1; //biến a được khai báo trong local scope 1
        console.log(a)
    }
    
    function three() {
        // Local Scope #3
        let a = 3; //biến a được khai báo trong local scope 3
        console.log(a);
    }
    one(); // in ra 1
    three(); //  in ra 3
    

    Block Statements

    Block statements như điều kiện if và switch hay vòng lặp for và while, không giống như function chúng không tạo ra 1 scope mới. Biến được định nghĩa bên trong Block statements sẽ vẫn giữ nguyên scope của nó.

    if (true) {
        // điều kiện if không tạo ra scope mới
        var name = 'Hammad'; // biến name vẫn thuộc global scope
    }
    
    console.log(name); // in ra 'Hammad'
    

    Javascript ES6 giới thiệu 2 từ khóa khai báo biến là let và const. Trái ngược với var, let và const hỗ trợ tạo ra local scope bên trong Block statements

    if (true) {
        var name = 'Hammad'; // biến name thuộc vào global scope
        let likes = 'Coding'; // biến likes thuộc vào local scope do từ khóa let
        const skills = 'JavaScript and PHP'; // biến skills thuộc vào local scope do từ khóa const
    }
    
    console.log(name); // in ra'Hammad'
    console.log(likes); // Uncaught ReferenceError: likes is not defined
    console.log(skills); // Uncaught ReferenceError: skills is not defined
    

    nguồn : Understanding Scope in JavaScript - Hammad Ahmed



  • Bài viết rất hữu ích. Mình có bổ xung thêm,
    Lí do và chúng ta nên sử dụng let thay cho var trong vòng for vì như vậy sẽ kiểm soát được biến i khi vòng for kết thúc, đảm bảo không ảnh hưởng với những đoạn code bên ngoài về sau (nếu như code bên ngoài cũng đang sử dụng một biến tên i)

    Với var

    for(var i = 0; i < 10; i++){
    
    }
    console.log(i) // kết quả = 10
    
    

    Với let

    for(let i = 0; i < 10; i++){
    
    }
    console.log(i) // i không tồn tại, i is not defined
    
    

Log in to reply