Understanding JavaScript variables

JavaScript variables are containers for storing data values. You can think of them as labeled storage boxes that hold information. Variables can store various types of data such as numbers, strings, objects, arrays, and more.

Declaring Variables:

In JavaScript, variables can be declared using the keywords var, let, or const:

var: This is the oldest way to declare variables. It has function scope and can be re-declared.

let: This allows block-level scope (meaning it only exists within the {} block where it is defined). It can be updated but not re-declared within the same scope.

const: This is also block-scoped but cannot be updated or re-declared. It is used when you want a constant value.

Examples:

// Declaring a variable with var

var x = 10; // Can be updated or re-declared

console.log(x); // Output: 10

// Declaring a variable with let

let y = 5; // Can be updated, but not re-declared within the same block

y = 8;

console.log(y); // Output: 8

// Declaring a constant with const

const z = 15; // Cannot be updated or re-declared

console.log(z); // Output: 15

Variable Naming Rules:

1. Must start with a letter, underscore (_), or dollar sign ($).

2. Can contain letters, numbers, underscores, or dollar signs (but cannot start with a number).

3. Case-sensitive (myVariable and myvariable are different).

Variables in JavaScript make it possible to handle dynamic data within a script.

JavaScript variables

What is block scope and function scope:

In JavaScript, scope refers to the visibility or accessibility of variables within different parts of a program. There are two main types of scope:

1. Function Scope

Variables declared with the var keyword are function-scoped, meaning they are accessible throughout the entire function where they are defined, even before the declaration due to a concept called hoisting. However, they are not accessible outside the function.

Example of Function Scope:
function testFunctionScope() {
  var x = 10;
  
  if (true) {
    var x = 20; // Still refers to the same 'x' variable (no block scope with var)
    console.log(x); // Output: 20
  }
  
  console.log(x); // Output: 20 (var is function-scoped, so 'x' is overwritten)
}

testFunctionScope();
console.log(x); // Error: x is not defined (x is not accessible outside the function)

2. Block Scope

Variables declared with let and const are block-scoped, meaning they are only accessible within the block {} where they are defined. A block can be any set of curly braces, such as those found in loops, conditionals, and functions.

Example of Block Scope:

function testBlockScope() {
  let y = 10;
  
  if (true) {
    let y = 20; // A new 'y' variable is created, scoped to this block
    console.log(y); // Output: 20
  }
  
  console.log(y); // Output: 10 (The original 'y' outside the block is not affected)
}

testBlockScope();
console.log(y); // Error: y is not defined (y is not accessible outside the function)

Key Differences:

1. Function Scope (var): Variables declared with var are accessible throughout the entire function, regardless of the block where they are declared.

2. Block Scope (let and const): Variables declared with let and const are only accessible within the block {} in which they are defined. They are not available outside that block.

Function scope means the variable is available throughout a function, but not outside it.

Block scope means the variable is only available within a specific block of code, such as a loop, conditional, or function block.

More points to consider:

Here are a few more important points to consider when declaring variables in JavaScript:

1. Hoisting

var declarations are hoisted to the top of their scope (function or global), meaning you can use a var variable before it’s declared without causing an error. However, the value will be undefined until the actual line where the variable is initialized.

console.log(a); // Output: undefined
var a = 5;
console.log(a); // Output: 5

let and const are also hoisted, but they are not initialized until their actual declaration. Accessing them before that results in a ReferenceError due to the temporal dead zone.

console.log(b); // Error: Cannot access 'b' before initialization
let b = 10;

2. Re-declaration

var can be re-declared and updated within the same scope, which can lead to unexpected behavior.

var x = 10;
var x = 20; // No error, x is re-declared

let and const cannot be re-declared within the same scope. This makes the code more predictable and helps prevent accidental reassignments.

let y = 10;
let y = 20; // Error: Identifier 'y' has already been declared

3. Const Variables

const must be initialized when declared and cannot be reassigned later. However, this applies to the variable itself, not the contents of objects or arrays declared with const.

const z = 30;
z = 40; // Error: Assignment to constant variable

const arr = [1, 2, 3];
arr.push(4); // This is allowed, as the array's contents can be modified
console.log(arr); // Output: [1, 2, 3, 4]

4. Global Scope

Variables declared outside any function or block are in the global scope, meaning they can be accessed from anywhere in the code. However, using global variables excessively can lead to name collisions or unintended overwriting, making the code harder to maintain.

var globalVar = "I'm global!";

function someFunction() {
  console.log(globalVar); // Output: I'm global!
}
someFunction();

5. Shadowing

You can have variables with the same name in different scopes. A variable declared inside a block or function can shadow a variable declared in an outer scope. The inner variable takes precedence within the scope it’s defined.

let x = 10;

function shadowingExample() {
  let x = 20; // This shadows the outer 'x'
  console.log(x); // Output: 20
}

shadowingExample();
console.log(x); // Output: 10 (The outer 'x' is not affected)

6. Variable Naming Conventions

Use meaningful names that describe the purpose of the variable.

Use camelCase for variables (e.g., myVariable), and avoid reserved keywords (like break, case, catch, etc.).

Start with a lowercase letter; do not start with a number.

Avoid using global variables when possible to reduce the risk of name collisions.

7. Immutable Bindings with const

Variables declared with const create immutable bindings. This means the variable cannot be reassigned, but the data inside a complex type (like an object or array) is still mutable.

const person = { name: "John" };
person.age = 30; // Allowed, as we are modifying the object’s content, not reassigning the variable

8. Avoid Implicit Globals

If you declare a variable without using var, let, or const, it becomes an implicit global variable. This can cause unintended behavior, especially if a variable is created inside a function or block.

function createGlobal() {
  implicitGlobal = 100; // No keyword, creates an implicit global variable
}
createGlobal();
console.log(implicitGlobal); // Output: 100

9. Variables in Loops

let is the preferred choice for declaring variables in loops, as it provides block scope, ensuring that the variable in each iteration has a unique binding.

for (let i = 0; i < 5; i++) {
  setTimeout(() => console.log(i), 100); // Outputs: 0, 1, 2, 3, 4
}

for (var j = 0; j < 5; j++) {
  setTimeout(() => console.log(j), 100); // Outputs: 5, 5, 5, 5, 5 (due to function scope)
}

By keeping these points in mind, you can write clearer, more predictable, and less error-prone code.

Hoisting in more details:

Hoisting is a JavaScript mechanism where variable and function declarations are moved to the top of their scope before the code execution. This means that you can use variables and functions before they are declared in the code, but with some specific behaviors.

How Hoisting Works:
JavaScript only hoists declarations, not initializations. The actual assignment or initialization of the variable happens where it is written in the code, but the declaration (just the fact that it exists) is moved to the top of its scope.

1. Variable Hoisting (with var)
When you declare a variable with var, JavaScript hoists the declaration to the top of the function or global scope. However, the initialization remains where it is written in the code, which can result in the variable being undefined if used before its assignment.

Example:
console.log(x); // Output: undefined
var x = 5;
console.log(x); // Output: 5

What happens internally:
var x; // Declaration is hoisted
console.log(x); // Output: undefined
x = 5; // Initialization happens here
console.log(x); // Output: 5

2. Function Hoisting

Functions declared using the function keyword are fully hoisted, meaning both their declarations and definitions are moved to the top of the scope. This allows you to call a function before it is defined in the code.

Example:
myFunction(); // Output: "Hello, world!"

function myFunction() {
  console.log("Hello, world!");
}

In this case, both the function declaration and definition are hoisted, so you can call myFunction before its actual location in the code.

3. let and const Variables (Not Hoisted Like var)

Although let and const variables are technically hoisted, they are not initialized until the line of code where they are declared. If you try to access them before their declaration, you'll get a ReferenceError. This is due to the temporal dead zone, which is the time between entering the block scope and the declaration of the variable.

Example with let:
console.log(a); // Error: Cannot access 'a' before initialization
let a = 10;

Example with const:
console.log(b); // Error: Cannot access 'b' before initialization
const b = 20;

Summary of Hoisting:

var: Declaration is hoisted to the top, but initialization stays in place. Variables declared with var can be used before they are initialized, but their value will be undefined.

function: Both the function declaration and its definition are hoisted, so the function can be called before it's defined.

let and const: These are also hoisted, but they are in the temporal dead zone until their actual declaration in the code, meaning they cannot be accessed before they are initialized.

Understanding hoisting helps avoid potential bugs, especially with variables declared using var. It also explains why let and const are safer choices since they prevent access before initialization.

Global scope and Parent scope:

Global scope:

In JavaScript, the global scope refers to the outermost scope of a script or program, where variables and functions declared outside of any function or block are accessible from anywhere in the code. Variables in the global scope are called global variables, and they can be accessed and modified by any part of the program.

Key Points about Global Scope:

1. Global Variables:
Variables declared outside any function or block (using var, let, or const) are in the global scope.

They can be accessed by any function, block, or script throughout the program.


var globalVar = "I am global!"; // Global variable
function someFunction() {
  console.log(globalVar); // Accessible inside a function
}
someFunction(); // Output: I am global!
console.log(globalVar); // Output: I am global!

2. var in Global Scope:
When you declare a variable with var in the global scope, it becomes a property of the window object (in browsers) or the global object (in other environments like Node.js).

var x = 10;
console.log(window.x); // Output: 10 (in a browser environment)

3. let and const in Global Scope:
Variables declared with let and const in the global scope are not added as properties of the global object (like window in browsers), but they are still accessible globally.

let y = 20;
const z = 30;
console.log(window.y); // Output: undefined
console.log(window.z); // Output: undefined
console.log(y, z); // Output: 20 30

4. Global Scope and Functions:
Functions declared in the global scope are also globally accessible.

function greet() {
  console.log("Hello, world!");
}

greet(); // Output: Hello, world!

5. Global Variables and Pollution:
Excessive use of global variables can lead to global scope pollution, where multiple variables or functions can unintentionally overwrite each other. This can make debugging difficult and lead to unpredictable behavior.

var myVar = "Global";
function setVar() {
  myVar = "Changed globally"; // Modifies the global variable
}

setVar();
console.log(myVar); // Output: Changed globally

6. Accidental Global Variables:
If you declare a variable without var, let, or const inside a function, it becomes an implicit global variable. This can cause unintended behavior.

function createGlobal() {
  implicitGlobal = 100; // No keyword, creates a global variable
}

createGlobal();
console.log(implicitGlobal); // Output: 100

Best Practices:

Minimize global variables: Use block or function scope with let, const, or var inside functions or blocks to prevent polluting the global scope.

Avoid accidental globals: Always use var, let, or const when declaring variables to avoid creating unintended global variables.

Use modular code: By organizing code into modules or functions, you reduce the need for global variables and prevent variable conflicts.

Summary:

The global scope is the top-level scope, where variables and functions are accessible throughout the entire program.

Variables declared globally can be accessed from anywhere, but too many global variables can lead to issues like name collisions and hard-to-debug code.

To avoid global scope pollution, it's best to use local variables with let, const, and modular code design.

Parent scope:

Parent scope refers to the scope that encloses another scope in JavaScript. In other words, if you have nested functions, blocks, or code structures, the parent scope is the outer scope that an inner scope can access. It defines what variables and functions are available for use in the child (or inner) scope.

Key Concept:
Outer (Parent) scope: The enclosing scope that holds variables accessible to nested (inner) scopes.

Inner (Child) scope: A scope nested within another scope. It can access variables from the parent scope, but the parent cannot access variables declared in the inner scope.

Example of Parent and Child Scopes:
let globalVar = "I'm in the global scope"; // Global scope (parent scope)

function outerFunction() {
  let outerVar = "I'm in the outer function scope"; // Parent scope of innerFunction

  function innerFunction() {
    let innerVar = "I'm in the inner function scope"; // Child scope (inner scope)
    
    // Accessing variables from parent scopes
    console.log(globalVar); // Output: "I'm in the global scope"
    console.log(outerVar); // Output: "I'm in the outer function scope"
  }

  innerFunction();
  console.log(innerVar); // Error: innerVar is not defined (can't access child scope)
}
outerFunction();

Explanation:

Global Scope: The variable globalVar is declared in the global scope, and it acts as the parent scope for all other scopes in the script.

Outer Function Scope: The variable outerVar is declared inside outerFunction. This scope acts as the parent scope for the innerFunction scope.

Inner Function Scope: The variable innerVar is declared inside innerFunction, which is a child scope of outerFunction. It can access outerVar and globalVar because they exist in the parent scopes, but outerFunction cannot access innerVar because it is declared inside a child scope.

Chain of Scopes:
When JavaScript looks for a variable inside a scope (like in innerFunction), it first checks the current scope. If the variable isn't found, it "looks up" to the parent scope. If it still doesn’t find the variable, it keeps going up through the chain of parent scopes (outer function, global scope) until it either finds the variable or reaches the top (global scope).

Example of Scope Chain:
let x = "global"; // Global (parent of everything)
function outer() {
  let x = "outer"; // Parent scope for the inner function
  
  function inner() {
    let x = "inner"; // Innermost (child scope)
    console.log(x); // Output: "inner" (found in child scope)
  }

  inner();
  console.log(x); // Output: "outer" (found in parent scope of outer function)
}
outer();
console.log(x); // Output: "global" (found in global scope)

Important Points:

1. Parent scopes can be:
Global scope (the outermost scope).
The scope of a function or block that encloses another function or block.

2. Inner (child) scopes can access variables from their parent scopes, but parent scopes cannot access variables from inner scopes.

3. Nested scopes: Multiple levels of scopes can exist (global → outer function → inner function). Variables in a child scope can "see" and use variables from all parent scopes up to the global scope.

4. Lexical scoping: JavaScript uses lexical scoping, which means that the scope of a variable is determined by its position in the source code. Inner scopes have access to their outer, or parent, scopes based on where they are defined in the code.

This scoping system allows for modular, reusable code and helps avoid variable name conflicts between different parts of a program.

In JavaScript, variables declared outside of any block ({}) or function are in the global scope (if declared globally) or parent scope (if within a function but outside of other blocks), meaning they can be accessed inside any block, function, or nested scope without needing to be re-declared.

Example:
let a = 10; // Global or parent scope
if (true) {
  console.log(a); // Output: 10 (Accessible inside the block without re-declaration)
}

function test() {
  console.log(a); // Output: 10 (Accessible inside the function without re-declaration)
}

test();

Explanation:
The variable a is declared in the global scope (or parent scope in a function).

Since blocks like if statements, loops, or functions have access to variables from their parent or global scope, you don't need to re-declare a inside the block. The block will "look up" the variable from the outer scope.

Nested Scope Access:
Variables defined in an outer scope are accessible in all inner or nested scopes, but not the other way around. Inner scope variables cannot be accessed by the outer scope.

Example:
let outerVar = 5;

function outerFunction() {
  let innerVar = 10;

  if (true) {
    console.log(outerVar); // Output: 5 (Accessible inside inner scope)
    console.log(innerVar); // Output: 10 (Accessible inside inner scope)
  }
}

outerFunction();
console.log(innerVar); // Error: innerVar is not defined (Can't access inner scope variable)

Key Points:
Outer scope variables are accessible in inner scopes (like inside blocks {} or functions).

Inner scope variables are not accessible from outer scopes. Variables declared inside {} or functions are confined to that specific block or function scope.

This behavior allows JavaScript to have nested scopes, where inner scopes can use outer scope variables, but outer scopes cannot use variables declared inside an inner scope.

This helps with organizing code, limiting variable access where needed, and preventing unintentional conflicts between variable names.

Difference between var, let and const

In JavaScript, var, let, and const are used to declare variables, but they differ in terms of scope, hoisting, and reassignment. Here's a detailed comparison:

1. Scope

var: Function-scoped.

let: Block-scoped.

const: Block-scoped.

Function Scope (for var):

Variables declared with var are function-scoped, meaning they are only accessible within the function in which they are declared. If declared outside a function, they are globally scoped.

function testVar() {
  var x = 10;
  if (true) {
    var x = 20;  // Same `x`, redefined within the same function
    console.log(x); // Output: 20
  }
  console.log(x); // Output: 20 (Still 20 because var is function-scoped)
}

testVar();

Block Scope (for let and const):

Variables declared with let and const are block-scoped, meaning they are only accessible within the block (e.g., within {}) where they are declared. They are not accessible outside the block.

function testLetConst() {
  let y = 10;
  const z = 30;
  if (true) {
    let y = 20;  // New `y` within the block
    const z = 40;  // New `z` within the block
    console.log(y); // Output: 20
    console.log(z); // Output: 40
  }
  console.log(y); // Output: 10 (Because the outer `y` is not affected)
  console.log(z); // Output: 30 (Because the outer `z` is not affected)
}

testLetConst();

2. Hoisting

var: Hoisted to the top of its function or global scope, but initialized with undefined.

let: Hoisted to the top of its block, but not initialized. Trying to access it before declaration results in a ReferenceError (Temporal Dead Zone).

const: Also hoisted to the top of its block, but like let, it's in the Temporal Dead Zone until it's initialized.

Example of var hoisting:
console.log(a);  // Output: undefined (because of hoisting)
var a = 10;
console.log(a);  // Output: 10

Example of let and const hoisting:
console.log(b);  // Error: Cannot access 'b' before initialization (Temporal Dead Zone)
let b = 20;

3. Reassignment

var: Can be reassigned and re-declared within the same scope.

let: Can be reassigned but cannot be re-declared within the same scope.

const: Cannot be reassigned or re-declared. However, for objects and arrays, the contents can be modified.

Example of Reassignment and
Redeclaration:
var x = 5;
x = 10;  // Allowed (Reassignment)
var x = 15;  // Allowed (Redeclaration)
console.log(x);  // Output: 15

let y = 20;
y = 30;  // Allowed (Reassignment)
let y = 40;  // Error: 'y' has already been declared (Redeclaration not allowed)

const z = 50;
z = 60;  // Error: Assignment to constant variable (Reassignment not allowed)

For objects and arrays with const:
const arr = [1, 2, 3];
arr.push(4);  // Allowed (Mutating the array)
console.log(arr);  // Output: [1, 2, 3, 4]

const obj = { name: "John" };
obj.name = "Jane";  // Allowed (Mutating the object)
console.log(obj);  // Output: { name: "Jane" }

4. Global Object Property

var: When declared globally, var adds the variable as a property of the global object (e.g., window in browsers).

let and const: Do not add the variable as a property of the global object when declared globally.

Example:
var a = 10;
let b = 20;

console.log(window.a);  // Output: 10 (because var is a global property)
console.log(window.b);  // Output: undefined (because let is not a global property)

5. Use Cases

var: Use only in legacy code or when function-scoped variables are explicitly needed.

let: Use when you need to declare a variable whose value will change or be reassigned.

const: Use when the value should not change (for primitives) or when you want to create immutable variable bindings for objects or arrays.

Summary

In modern JavaScript development, it's recommended to use let and const instead of var to avoid potential issues related to hoisting and scope confusion.

Difference between declaration and assignment 

The difference between declaration and assignment in JavaScript lies in their purposes and functions:

1. Declaration
Declaring a variable means introducing it to the program, so the program knows it exists.

This is done using keywords like var, let, or const.

When declared the memory is allocated for the variable.

The variable is created but not necessarily initialized with a value.

Syntax:
let x; // Declaration

Default value:
Declared variables are automatically assigned a value of undefined unless explicitly initialized.

Example:
let num; // Declaration of variable `num`
console.log(num); // Output: undefined (because it hasn't been assigned a value)

2. Assignment

Assigning a value to a variable means giving it a specific value.

This can be done during or after declaratIon
The value is stored in the memory location associated with the variable.

Syntax:
x = 10; // Assignment

Reassignment:
For let and var, you can reassign values multiple times. For const, you cannot reassign values.

Example:
let num; // Declaration
num = 5; // Assignment
console.log(num); // Output: 5

Declaration and Assignment Combined
You can declare and assign a value in a single step.

let x = 10; // Declaration and assignment

let name = "Alice"; // Declaration + Assignment
console.log(name); // Output: Alice


Post a Comment

Previous Post Next Post

Ad01

Ad02