DEV Community

Cover image for Mastering JavaScript Scopes: How var, let, and const Behave in Different Scopes
Anisubhra Sarkar (Ani)
Anisubhra Sarkar (Ani)

Posted on

Mastering JavaScript Scopes: How var, let, and const Behave in Different Scopes

JavaScript scope defines where variables, functions, and objects can be accessed or referenced in your code. A clear understanding of scope and how variables (var, let, and const) behave in different scopes is essential for writing clean, maintainable, and bug-free JavaScript.

In this article, we’ll explore the different types of scopes in JavaScript, including global, function, block, script, and module scopes, and the behavior of var, let, and const within each scope.


1. Types of Scopes in JavaScript

Global Scope

  • Variables declared outside of any function, block, or module belong to the global scope.
  • These variables can be accessed from anywhere in your code.
  • In browsers, variables declared with var are attached to the window object, while let and const are not.

Example:

var globalVar = "I am global"; // Attached to `window`
let globalLet = "I am also global"; // Not attached to `window`
const globalConst = "I am globally constant"; // Not attached to `window`

console.log(globalVar);       // Output: "I am global"
console.log(window.globalVar); // Output: "I am global"
console.log(window.globalLet); // Output: undefined
console.log(window.globalConst); // Output: undefined
Enter fullscreen mode Exit fullscreen mode

Function Scope

  • Variables declared inside a function are only accessible within that function.
  • Both var, let, and const respect function scope.

Example:

function myFunction() {
  var functionVar = "I am inside a function";
  let functionLet = "I am also inside a function";
  const functionConst = "I am constant inside a function";

  console.log(functionVar);   // Output: "I am inside a function"
  console.log(functionLet);   // Output: "I am also inside a function"
  console.log(functionConst); // Output: "I am constant inside a function"
}

myFunction();

// Outside the function
console.log(typeof functionVar); // Output: "undefined"
console.log(typeof functionLet); // Output: "undefined"
console.log(typeof functionConst); // Output: "undefined"
Enter fullscreen mode Exit fullscreen mode

Block Scope

  • A block is any code enclosed in {} (e.g., loops, if statements, etc.).
  • Variables declared with let and const are block-scoped, meaning they are accessible only inside the block in which they are defined.
  • var does not respect block scope—it is function-scoped or global-scoped.

Example:

{
  var blockVar = "I am not block scoped"; // Escapes the block
  let blockLet = "I am block scoped";    // Block-scoped
  const blockConst = "I am also block scoped"; // Block-scoped

  console.log(blockVar);   // Output: "I am not block scoped"
  console.log(blockLet);   // Output: "I am block scoped"
  console.log(blockConst); // Output: "I am also block scoped"
}

console.log(blockVar);   // Output: "I am not block scoped"
console.log(typeof blockLet);   // Output: "undefined"
console.log(typeof blockConst); // Output: "undefined"
Enter fullscreen mode Exit fullscreen mode

Script Scope

  • Script scope applies when JavaScript is loaded as regular <script> tags (not as ES6 modules).
  • Variables declared with var in script scope are attached to the global scope (window object in browsers).
  • Variables declared with let and const are limited to the script itself and are not attached to the global window object.

Example:

<script>
  var scriptVar = "I am script-scoped with var";
  let scriptLet = "I am script-scoped with let";
  const scriptConst = "I am constant in script";

  console.log(window.scriptVar);   // Output: "I am script-scoped with var"
  console.log(window.scriptLet);   // Output: undefined
  console.log(window.scriptConst); // Output: undefined
</script>
Enter fullscreen mode Exit fullscreen mode

Module Scope

  • Module scope applies when JavaScript files are loaded with <script type="module"> or imported into another ES6 module.
  • Variables declared in a module are scoped to that module and are not added to the global window object.
  • Modules are executed in strict mode by default, which enforces stricter parsing and error handling.
  • You can use export and import to share variables, functions, or classes between modules.

Example:

<script type="module">
  const moduleScopedVar = "I am scoped to the module";
  console.log(moduleScopedVar); // Output: "I am scoped to the module"
  console.log(window.moduleScopedVar); // Output: undefined
</script>
Enter fullscreen mode Exit fullscreen mode

Exporting and Importing:

// moduleA.js
export const greeting = "Hello from moduleA";
export function sayHello() {
  console.log(greeting);
}

// moduleB.js
import { greeting, sayHello } from './moduleA.js';

console.log(greeting); // Output: "Hello from moduleA"
sayHello(); // Output: "Hello from moduleA"
Enter fullscreen mode Exit fullscreen mode

Behavior of var, let, and const Across Scopes

Scope var Behavior let Behavior const Behavior
Global Scope Attaches to window. Does not attach to window. Does not attach to window.
Function Scope Function-scoped. Function-scoped. Function-scoped.
Block Scope Does not respect block scope. Respects block scope. Respects block scope.
Script Scope Attached to window. Scoped to the script itself. Scoped to the script itself.
Module Scope Scoped to the module itself. Scoped to the module itself. Scoped to the module itself.

Choosing Between var, let, and const

var

  • Avoid using var in modern JavaScript—it is prone to bugs due to lack of block scope and hoisting issues.

let

  • Use let when you need a variable that can be reassigned within its scope (e.g., in loops).

const

  • Use const by default. It ensures immutability within its scope, making code safer and easier to understand.

Best Practices

  1. Use const by default:

    • Declare variables with const unless you know their value needs to change.
  2. Use let for reassigned variables:

    • Use let for variables that will be updated or reassigned.
  3. Avoid var:

    • Stick to let and const to avoid scope-related bugs and global pollution.
  4. Use ES6 modules for modern projects:

    • Prefer <script type="module"> for modular, scalable JavaScript codebases.

Conclusion

Understanding JavaScript scopes—global, function, block, script, and module—is crucial for writing predictable and maintainable code. The behavior of var, let, and const differs significantly across these scopes, and knowing how they interact can help you make better decisions about variable declarations.😊

Top comments (0)