I have learned the basics of variable hoisting in JavaScript, and am now trying to enhance it by doing some exercises. I’ve come across this piece of code:
function makeAdders(lst) { var ar = []; for(var i = 0; i < lst.length; i ++) { var n = lst[i]; ar[i] = (x) => x + n; } return ar; } var adders = makeAdders([6,3,5]); adders.forEach((adder) => { console.log(adder(100)); })
This code first creates an array of functions from a given list. Each function adds the same passed number (in this case 100) to a particular value of the list and prints the result. The expected output of this is: 106, 103, 105, and you can achieve this if you use “let” instead of “var” in the for loop. The output of the above code though, is 105, 105, 105, and after some research, I have come to the conclusion that it is because variables i and n are being hoisted (since var is hoisted and let is not).
However, I cannot quite wrap my head around what exactly is going on here and how variable hoisting in this code prevents it from achieving the expected result. Could somebody please help me understand what exactly is happening here? Thank you in advance!
Advertisement
Answer
var
hoist based on file
(if the variable is in global scope) or function
(if the variable is inside a function)
let
doesn’t hoist and is hijacked(only scoped) to the nearest curly brackets {
… }
The code has n
that is hoisted (not to the for scope inside {...body of for...}
) but to the scope of makeAdders
function
now when the code
var adders = makeAdders([6,3,5]);
is exectued we have an array of adders function
s that all have closure
to the one shared n
variable
(closure
is when a function can access its lexical scope even though it’s executed in completely another scope)
while n
is shared between all function
s the last n
is set to the value of the last element in the input array which happened to be 5 for now
that’s why after all functions are created n
have 5
and all adders
will return 5 + x