JavaScript Closures

Jul 11, 2024

JavaScript Closures

Introduction

  • Closures are important for JavaScript developer interviews.
  • Closures overlap with scoping concepts.
  • Recommendation to understand JavaScript scoping before diving into closures.

What Are Closures?

  • A closure occurs when a function is defined inside another function and accesses variables from the outer function.
    • Example to illustrate closures:
      function funcOne() {
        var age = 29;
        function funcTwo() {
          console.log(age);
        }
        return funcTwo;
      }
      var newFunc = funcOne();
      newFunc(); // prints 29
      
  • Definition: Anytime a function uses variables from an outer function's scope, it is a closure.

Behavior and Mechanism

  • Normally, variables in a function are garbage collected after the function execution.
  • With closures, the variables are retained in memory if an inner function needs them.
  • Example illustrating closure keeping the state updated:
    function outer() {
      let age = 29;
      function inner() {
        console.log(age);
      }
      age = 30; 
      return inner;
    }
    const innerFunc = outer();
    innerFunc(); // prints 30
    
  • Closures ensure the most up-to-date value of variables is used.

Importance and Use Cases

  • Historically, closures were used to create private variables, which are not accessible outside their scope.
  • In modern JS, modules provide a way to achieve similar functionality, making closures less critical for some cases.
  • Closures enable higher-order functions, such as function factories:
    function createElementCreator(type) {
        return function() {
            return document.createElement(type);
        }
    }
    const createDiv = createElementCreator('div');
    const createSpan = createElementCreator('span');
    const divEl = createDiv();
    const spanEl = createSpan();
    

Common Interview Questions

  • Classic Closure Question: Involving let vs var in loops
    • Example showing var behavior:
      for (var i = 0; i < 3; i++) {
        setTimeout(() => console.log(i), 100);
      }
      // Prints 3, 3, 3
      
    • Example showing let behavior:
      for (let i = 0; i < 3; i++) {
        setTimeout(() => console.log(i), 100);
      }
      // Prints 0, 1, 2
      
  • Explanation:
    • var has function scope, leading to a single i variable shared across all iterations.
    • let has block scope, creating a new i for each iteration.

Conclusion

  • Closures integrate with normal scoping rules but apply when functions return or contain other functions.
  • Essential for understanding advanced JavaScript and crucial for job interviews.
  • Additional resources and courses available for in-depth JavaScript learning.