Skip to content

Instantly share code, notes, and snippets.

@hai5nguy
Last active May 22, 2018 13:48
Show Gist options
  • Save hai5nguy/2652a7960bf3efb21c95b3bc4d7e204f to your computer and use it in GitHub Desktop.
Save hai5nguy/2652a7960bf3efb21c95b3bc4d7e204f to your computer and use it in GitHub Desktop.
const arr = [10, 12]; // for simplicity, let's only have 2 runs
for (let i = 0; i < arr.length; i++) {
setTimeout(() => {
console.log('The index of this number is: ' + i);
}, 3000);
}
// ///////////////////////////////
// example with the let keyword
// ///////////////////////////////
// the following is how a computer will run the above for loop
// (run 1)
// SET i = 0, CHECK 0 < 2, RUN LOOP
// (this is where it gets crazy)
// MAKE A COPY OF EVERY VARIABLE IN THIS FUNCTION (including arr and i, this copy is called the ENVIRONMENT)
// MAKE A NEW FUNCTION AND MAKE SURE THAT IT KNOWS THE ENVIRONMENT above it. (so the function at line 3 knows what the arr and i variables are)
//
// CALL SETTIMEOUT AND PUT THE NEW FUNCTION (with its environment) INTO THE TIMING QUEUE:
// timing queue:
// 0: function () {
// (arr = [10, 12], i = 0) <- these variables are not explicitly set in the new function, but they are there!!! because they are part of the "ENVIRONMENT"
// console.log('the index is', i) } <- run this after 3 seconds from now. now = (new Date()).getTime()
// }
//
// SET i = i + 1, GO TO START OF LOOP
// (run 2)
// SET i = 1, CHECK 0 < 2, RUN LOOP
// (this is where it gets crazy)
// MAKE A COPY OF EVERY VARIABLE IN THIS FUNCTION (including arr and i, this copy is called the ENVIRONMENT)
// MAKE A NEW FUNCTION AND MAKE SURE THAT IT KNOWS THE ENVIRONMENT above it. (so the function at line 3 knows what the arr and i variables are)
//
// CALL SETTIMEOUT AND PUT THE NEW FUNCTION (with its environment) INTO THE TIMING QUEUE:
// timing queue:
// 0: function () {
// (arr = [10, 12], i = 0) <- these variables are not explicitly set in the new function, but they are there because they are part of the "ENVIRONMENT"
// console.log('the index is', i) } <- run this after 3 seconds from now. now = (new Date()).getTime()
// }
// 1: function () {
// (arr = [10, 12], i = 1) <- these variables are not explicitly set in the new function, but they are there because they are part of the "ENVIRONMENT"
// console.log('the index is', i) } <- run this after 3 seconds from now. now = (new Date()).getTime()
// }
//
// SET i = i + 1, GO TO START OF LOOP
// (run 3)
// SET i = 2, CHECK 2 < 2, (false!), EXIT LOOP
// EXIT THE ENTIRE FUNCTION.
// ... DO OTHER STUFF (javascipt is all about non-blocking and async stuff, like render this, run other functions, listen for user events, clicks, blah blah blah, and also...)
// CHECK THE TIMING QUEUE!
// GO THROUGH THE TIMING QUEUE
// FOR EACH ITEM, IF (CURRENT_TIME - SET_TIME > INTERVAL), CURRENT_TIME = (new Date()).getTime();
// SET_TIME = the timestamp when you called setTimeout()
// INTERVAL = the interval you gave setTimeout(fn, interval) = 3000 milliseconds
// RUN THE ITEM/FUNCTION
// (so finally after 3 sec, you have)
// the index is 0
// the index is 1
const arr = [10, 12]; // for simplicity, let's only have 2 runs
for (var i = 0; i < arr.length; i++) {
setTimeout(() => {
console.log('The index of this number is: ' + i);
}, 3000);
}
// ///////////////////////////////
// example with the VAR keyword
// ///////////////////////////////
// the following is how a computer will run the above for loop
// (run 1)
// SET i = 0, CHECK 0 < 2, RUN LOOP
// (this is where it gets crazy)
// MAKE A NEW FUNCTION AND GIVE IT THE REFERENCE TO THE CURRENT ENVIRONMENT (this is where var differs from let, the current environment is not copied! it is reference)
// CALL SETTIMEOUT AND PUT THE NEW FUNCTION (with its environment) INTO THE TIMING QUEUE:
// timing queue:
// 0: function () {
// (arr = [10, 12], i = 0) <- watch this i value closely!
// console.log('the index is', i) }
// }
//
// SET i = i + 1, GO TO START OF LOOP (a change in i !!!!!!!!!!!!!)
// (run 2)
// SET i = 1, CHECK 0 < 2, RUN LOOP
// (this is where it gets crazy)
// MAKE A NEW FUNCTION AND GIVE IT THE REFERENCE TO THE CURRENT ENVIRONMENT (this is where var differs from let, the current environment is not copied! it is reference)
// CALL SETTIMEOUT AND PUT THE NEW FUNCTION (with its environment) INTO THE TIMING QUEUE:
// timing queue:
// 0: function () {
// (arr = [10, 12], i = 1) <- wtf!!!!!!!!!!!
// (WHY IS i = 1????, i = 1 because you are using the SAME environment as the one above! the environment was referenced so any change
// to the environment from ANYWHERE will be reflected here)
// console.log('the index is', i) }
// }
// 1: function () {
// (arr = [10, 12], i = 1) <- this is expected
// console.log('the index is', i) }
// }
//
// SET i = i + 1, GO TO START OF LOOP (i = 2, notice now that the item functions in the timing queue will print 2 instead of 1)
// (run 3)
// SET i = 2, CHECK 2 < 2, (false!), EXIT LOOP
// EXIT THE ENTIRE FUNCTION.
// ... DO OTHER STUFF (javascipt is all about non-blocking and async stuff, like render this, run other functions, listen for user events, clicks, blah blah blah, and also...)
// CHECK THE TIMING QUEUE!
// GO THROUGH THE TIMING QUEUE
// FOR EACH ITEM, IF (CURRENT_TIME - SET_TIME > INTERVAL), CURRENT_TIME = (new Date()).getTime();
// SET_TIME = the timestamp when you called setTimeout()
// INTERVAL = the interval you gave setTimeout(fn, interval) = 3000 milliseconds
// RUN THE ITEM/FUNCTION
// (so finally after 3 sec, you have)
// the index is 2
// the index is 2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment