📘
snesjhon
  • You Should Know
  • Personal
    • Blogs
      • I'll never complain about web tooling again.
      • vscodevim
  • JavaScript
    • Closures
      • Closure Q1
    • Values
      • Primitive vs Reference
      • Accessing by value and reference
    • Function
      • call, apply, bind
      • Pass by value
      • Different types of Scopes
      • Context vs Scope
      • Parse Time Vs Run Time
    • Hosting
      • Are Let & Const Hoisted?
      • Hoisting Q1
      • Hoisting Q2
    • Standard Objects
      • Math
        • Math.log10
        • Math.pow()
    • Array
      • Apply
      • Slice vs Splice vs Split
    • This
      • This - Q1
    • TypeScript
      • as const
    • FAQs
      • Modulo Operator
      • Timeout
      • Declarative vs Imperative
      • ++i vs. i++
    • Interview Questions
  • react
    • FAQs
  • Ruby
    • Debugging
    • Symbols
    • Intro
  • Algorithms
    • Sliding Window
      • minSubArrayLen
      • maxSubArraySum
      • findLongestSubstring
    • Frequency Counter
      • sameFrequency
    • Recursion
      • nestedEvenSum
      • flatten
      • Reverse a String
      • Fibonnacci
    • Searching
      • overlappingIntervals
      • twoStringSearch
      • binarySearch
    • Sort - Elementary
      • Selection Sort
      • Bubble Sort
      • Insertion Sort
      • quickSort
    • Sort - Intermediate
      • Radix Sort
      • Merge Sort
    • FAQs
  • Data Structures
    • Breadth First Search
    • Linked Lists
      • Singly Linked Lists
    • FAQs
  • Code Challenges
    • LeetCode
      • removeDuplicates
    • Hacker Rank
      • twoSums
      • Sock Merchant
    • Hacker Rank - Medium
      • New Year Chaos
  • Databases
    • SQL
Powered by GitBook
On this page
  • What would this print out?
  • How would you fix this?
  • Resources
  1. JavaScript
  2. Closures

Closure Q1

What would this print out?

var arr = [1,2,3,4];

function closure(){
    for(var i = 0; i < arr.length; i++){
        setTimeout(function(){
            console.log(i)
        }, 100)
    }
}

closure()
var arr = [1,2,3,4];

function closure(){
    for(var i = 0; i < arr.length; i++){
        setTimeout(function(){
            console.log(i)
        }, 100)
    }
}

closure();

It would print out:

4
4
4
4

This is because the function gets called and the loop happens, but the setTimeout isn't called until later (because of the timeout) and at that point, the i is at 4 because the loop has already ran. This happens because var i is not blocked scoped, but rather function scoped

How would you fix this?

var arr = [1,2,3,4];

function closure(){
    for(var i = 0; i < arr.length; i++){
        setTimeout(function(){
            console.log(i)
        }, 100)
    }
}

closure()

There are a couple of ways to fix this closure problem.

Using Let

var arr = [1,2,3,4];

function closure(){
    for(let i = 0; i < arr.length; i++){
        setTimeout(function(){
            console.log(i)
        }, 100)
    }
}

closure()

This would be the quickest way because using let allows you to use BLOCK SCOPING. This means that instead of using a var which uses FUNCTION SCOPING, the let is recreated (and uses the previous value) every time the for loop runs. That means that when setTimeout is executed, the closure value of i is persisted in memory because it a new let is created and incremented from the previous value

Using IIFE

var arr = [1, 2, 3, 4];

function closure() {
  for (var i = 0; i < arr.length; i++) {
    (function (item) {
      setTimeout(function () {
        console.log(item);
      }, 100);
    })(i);
  }
}

closure();

And IIFE is immediately invoked, at the iteration during which it passes the current value of the i so that (because of closures) the item param is then able to be referenced when the callback function is called with setTimeout

Using `bind`

var arr = [1,2,3,4];

function closure(){
    for(var i = 0; i < arr.length; i++){
        setTimeout(function(item){
            console.log(item)
        }.bind(null, i), 100)
    }
}

closure()

Using bind is another way of passing and encapsulating a variable's content based on when it was called. So when setTimeout is invoked then it's "bounded" to what the variable i was at the time it was called.

Resources

Last updated 4 years ago

https://stackoverflow.com/questions/59170277/javascript-understanding-let-scope-inside-for-loop