Solving JavaScript's Most NOTORIOUS Interview Question
HTML-код
- Опубликовано: 26 ноя 2024
- Can you solve this notorious JavaScript coding interview "trick" question?
Prepping for your frontend interviews? Use code "conner" for a discount on my course FrontendExpert:
www.frontendex...
LinkedIn: / connerardman
TikTok: / connerardman
Video/Coding Gear: www.amazon.com...
A programmer puts two glasses on his bedside table before going to sleep. A full one, in case he gets thirsty, and an empty one, in case he doesn’t
...and a prescription one, in case he can't get that bug outta his head.
I thought you were referring to spectacles.
😂
I don't get it.
😂😂😂😂😂😂😂
If this is an interview question, I'm walking out the door and finding a better place
Kekw, not knowing basics of that horrendous language is like programming in C depending only on compiler
@@NaN-se8ye ok. thats why gdb exists though. those js questions arent scary, they are silly. and any company that asks silly questions is a silly company.
you don't want free money?
@@HelloThere-xs8ss ok you can walk out all interviews then good luck
if every time you get somerhitn you belive is silly you just walk out good luck running any business or any type pf relations really
@@ko-Daegu why did you take my statement personally?
Using `var` in this example is the equivalent of declaring a global variable (var i = 0) right before the loop.
setTimeout's are only called after the synchronous code finishes executing, (ie, after the loop has finished, and i has reached 3).
the console.log(i) inside of them prints 3 because the 'i' they have access to is the one in the global scope, which has a value of 3.
Using let on the other hand is equivalent to having a (let i = 0/1..../n) statement on each iteration of the loop.
Since every iteration has its own, local declaration of the variable i, the setTimeouts here get access to different (i)s, hence the different values.
this questions tests your knowledge on two key JS concepts : variable scopes/hoisting, and the event loop
Still not clear, set time out to 10 sec for let, if it is a sync call how does it pints 012, for loop has already finished before time out.
@@akb4076the `setTimeout()` calls are what's called a Macro task.
Macro task are *not* executed synchronously, instead, they are added to a queue.
The tasks in this queue are executed when *_and only when_* the call stack (ie the one that contains synchronous code) is empty. So even if the loop took 10 minutes to finish executing, the first setTimeout is only gonna be executed after that, since it’s a macro task.
Now, the reason the console.log’s print the correct values in the let example, is because the setTimeouts are `scheduled` to run with local values of i, It doesn’t matter when they’re going to execute their callback function, because that function has already been `configured` to run with the correct value of i (0, 1, and 2 respectively)
The only reason the `var` example prints 3 is because `i` in this instance is a global variable, there’s no `configuring` being done, the callback functions are just told to print the value of a global variable, and that global variable happens to have a value of 3.
For more on the event loop, I highly recommend watching this talk -> ruclips.net/video/8aGhZQkoFbQ/видео.html
Thanks for the explanation, since the video literally explains nothing.
@@abdoufma that was a great explanation!
@@Никита-р1в5и The video explains it better, you're just too new to understand the terminology he used. Don't criticize someones intellect because your own lack of understanding. That's ironic at best and sad at worst.
Pro tip: don’t use var, use let. There’s never a good reason to use var.
Let doesn't work in IE11 . . .dont ask how i know 😂 😭
@@NathanHedglin just stop supporting IE11 in 2023. It's support from Microsoft stopped on June 15th 2022 ;)
@@NathanHedglin No one used IE11 except for grandparents
var was significantly more performant than let for a while. Pro tip: There are no pro tips with anything js/ts, at the end of the day they are shit languages, try to avoid anonymous/arrow/lambda/closures also, they are heap allocated, that is shitty. Most javascript devs don’t know what the heap is unfortunately, but basically heap is O log n stack is O 1
Let doesn't allow you to redeclare global values, which is done quite commonly when dealing with modules or other global dependencies, please don't spread "pro tips" when you don't understand a feature.
var module = module || {}; // let would crash here
For anyone confused, let creates new variables in memory for each iteration. i is not the same i for each iteration. This is why the closures 'remember' different i values.
For var, var is not being recreated for each block and iteration. It's value is just getting updated from 0 to 3 (due to last increment when i = 2)/
It's also important to remember that due to the asynchronous nature of setTimeout. closures won't run until after 100ms. However, the for loop will complete before that 100ms. This allows the closures to ONLY refer to the changed var variable, not their newly created i's when let is used.
You need to be top cmnt.
Good explanation.
Thanks i understand it now
Even if the loop takes more than 100ms, setTimeout will not execute until the current function is finished.
Best explanation I’ve seen in these comments
your answer was more complicated than than the question
I had to google set timeout and that it is asynchronous. Then I went back and watched the explanation again and now I understand.
@@Stefan-xm9qb Thanks bro. yes, you explained better.
I saw "var" and immediately went 💀
var is hoisted to the nearest enclosing scope which is the global scope (from the example in the video). var also has a special behavior of reinitialization meaning for each loop it does not create a new variable but instead it modifies the already declared variables which is this case 'i'
now because the closure that created inside set timeout calls accessing 'i' which is declared using var, all of 3 closure actually accessing same variable (literally same variable from memory, not just its name 'i'). and because the executions itself is deffered using timeouts, when that 3 callbacks is actually being executed, it will read the latest value of 'i' which is the value of integer 3. thats why we saw the ouputs of 3 3 3 in the video
Var hosits the variable to global... So after 100 ms the var will be 3 (as loop would be finished)
When u use let.. it creates a closure.. so the i is binded to the setTimeout..so even if u set Timeout for 1 hour .. it will remember the state of i
As a beginner and not native English speaker I had to watch it like 6 times but I get it now. Thank you! Great problem to understand the difference between let and var
Same here 😭
Count me in 👋💀
This makes minimal sense to me, but I have no doubt that this guy is helpful to the people who are into this field. Clear spoken, good pace, good quality. Keep going man!!
minimal sense? why's that?
@@bigsmoke1284 I’m not super big into coding so I couldn’t fully experience his teaching. But I have no doubt in my mind he’s saving some peoples jobs right now 😂
i see. yes, i agree with you. this is definitely a more advanced concept within javascript/programming itself. this is most likely to be a question in mid/senior interviews.
most sane programming language
most insane comment
Yes, javascript is a good language
Is this sarcasm?
@@nickbh15 obviously
@@nickbh15yea, js isnt very good
My previous test lead does this in interviews. I wouldn’t comment like you’re above this. The simplest way to find if a candidate is real or bs is by asking list of questions that go from very basic to more complex. You can identify someone who is faking it very quickly with the basic questions.
What kind of drop kick asks a question like this in an interview?
Exactly my question - and noturious... uhm...
Lol, I was asked this question in the interview. 😂
Funny is that I was saying it will return 0,1,2, and the interviewer was insisting it would be 3,3,3. When I asked why he couldn't answer and moved to another question.
@@ivan33776 do you then know the answer to this
let a = 1;
setTimeout(() => console.log(a))
a += 1
Knowing this shows how far your skill is in the language, python has something similar called closure late binding, but js is more out rages with that let/var difference
Got asked this question just today and I was already looking for answers. Thank you.
This is actually present in C++ too. There you have options to copy variables or to refer to them. Later will result in a similar behavior.
yes, but fortunately in c++ that kind of thing makes sense. if you write this example in c++ and capture by reference in the closure, then it's obvious that the result will be 3 3 3. in javascript, it's not at all obvious unless you know that `var` doesn't actually declare a variable where it says it does; it declares a function scoped variable - so even though you declared a variable in the for loop, that variable is scoped outside of the for loop. it's completely insane and unexpected behavior, unlike c++
Make sure your babel/typescript/whatever transpiler does not replace let with var which it does if you use some ancient settings
You can also use function under function inside for loop. So that you don't need to use let.#closure
I agree this is the most notorious problem of JavaScript. Many interviewer and interviwee know the answer but will fumble when ask to explain. 😅😅 I myself have landed in this problem during interview
Very informative! Thank you so so much! :)
I think this can be used as one of those “what English sounds like to people who don’t speak English” soundtracks
Another way to get the iteration correctly without changing var is to use the third param on setTimeout instead of the arrow function. But yeah, its better drop var and use let
Key point is understanding scope, closures and var, let, const. The question isn’t silly it tests how many hours you have spend with the language and so how productive of a developer you are. Yeah sure I would have more fun solving some white board problem related to graph traversing or inverting a binary search tree but let’s be honest companies look for value vs money and often jobs aren’t gonna need you to do ground breaking shit that requires big brain logic.
Also possible solution
for(var i = 0; i{console.log(val)}, 100, i)
}
As a non JS Programmer, the more interesting thing to me is that setTimeout apparently doesn't block.
If it did, browsers would suck
Function scope was well understood before let became a keyword, just had to do something like this:
for (var i = 0; i < 3; i++) { (function(n) { setTimeout(console.log.bind(null, n), 100); })(i); }
Or something like this:
for(let i = 0; i < 3; i++) {
setTimeout(console.log, 100, i)
}
I wrote let 'cause it's preferable but the solution work either var or let.
@@whitefercho Umm, but not in JavaScript 1.1. That version cast a long and nasty and awkward shadow. Oh, how I miss her (but not really).
@@icillay uhm, I started this year learning javascript ES6. At least, I get why is there the method bind you applied on your solution and I liked as well. It is to use a function as an argument and there's an IIFE to make it work, am I wrong?
thats horrific
The algorithms are getting scary good cuz we just went over this in class last night 😮
That is why it is good to understand JavaScript jundamemtals... For this reason i avoid using var to avoid bugs
But would would it log out 3 though? Isn’t i < 2?
i is incremented to 3 and thus the loop condition is no longer true and we exit the loop. However, i is still 3 and after 100ms, it will print out three 3's.
@@eliasgeirdal676 so the point is here that the setTimeOut func is going to work after 100 ms and for loop is completing faster than 100 ms?
Probably the last chill prog video im putting out; like n subscribe
This was explained very well a few years back by Surma and Jake on the HTTP 203 v/podcast 🙃
So basically if you are a JS programmer from the last 10 years, you will never run into this problem because you would automatically declare variables with let and never use var.
lol fr
Alternatively, we can create another function(new closure) with own argument “i” outside of loop and it will work just fine too
If you don't know what you doing, just use let or const please 😭😭
That's why in java, to use a variable in a lambda, it needs to at least be effectively final
Most notorious interview question - have never seen this in my life, in fact, if I did I'd leave the room right away.
You sir, just got yourself a new subscriber
If interviewer says you cannot use var. Just wrap settimeout inside a function and pass I in the function call as an argument
Never even knew that var existed. I hardly use let. Mostly const
Also we can use IIFE and binding
yeah for sure i understood this well 😅
i am not gonna lie but i did this question in less that 4sec but interviewer set thecondition to 1
Why you use settimeout inside a for loop, just for printing "0 1 2" ?
Instead, you can just get rid of that settimeout, and directly use "console.log" without "setimeout"
This is the same in golang and probably lots of other languages with closure / anonymous functions
Its really just understanding the difference between var and let
Right im confused on how this is notorious. Reading a couple sentences on scope would make it make sense
@@razorred0 so, could you explain?
@@razorred0 this is not about scope
Let vs var lol. Most people always use one or the other, it’d be nice if people used the appropriate choice
It will print 333 bcz of var and 012 if we use let
Man, that was one of the most confusing thing I've ever seen in JS. Like I didn't know we have a new "i" in each iteration in case of "let". Though, doesn't that make it slower than "var" since it's creating a new "i"?
Clear as mud
Learnt new thing today. Thanks
Also we could use IIFE function to fix this issue.
That's the correct answer!
How do you get the different colors, which extensions do you use?
You mean the theme? It's called Monokai I think
In what practical situatuon can this be useful?
Is this a function that is used in real production?
Yes, setTineout is an extremely common function in JavaScript. This specific case almost never comes up though.
@@ConnerArdman aha. Ive never used it. Is it used instead of promises?
@@AndrewTSq Not really, it's just an entirely different concept. Promises allow you to wait for some asynchronous action to complete. setTimeout sets a timer, so it lets you wait for some predetermined amount of time.
These are used a lot for things like animations, polling requests, literal timers, etc.
I hate these kinds of questions. They should be asking "This is crap code, here's what I wanted the code to do. How would you write it correctly?"
As an entry level job if I get this I'm working in lidls
Hence why you're told to always use let instead of var
I saw the issue immediately lmao
Man i had to watch many times to get it, i think there is an easier explanation 💀
i still have no clue.
Before let was invented we had to wrap setTimeOut in an iife
This is actually a race condition and on a extremely throttled processor or during certain events or on really slow hardware (although I’m not sure the intersection between a processor that takes 100ms between each iteration and a processor that can actually run JavaScript ) it could output something other like 0 1 2
There isn't a race condition. This would be true for similar code in some other languages, but not JavaScript. You would get the same result with a 0ms timeout and a for loop to a million to make it take longer. JavaScript only runs in one thread, so the timeout callback can't run until the call stack is empty (e.g. the for loop completes). All of the timeout callbacks that are ready to run are held in a queue and only get pushed onto the call stack once it is free. As a result, timeouts in JavaScript are minimum amounts of time until code runs, and regardless of hardware the callbacks will never run before the loop completes.
@@ConnerArdman ahhh that makes complete sense thank you for the quick reply Conner
race condition in a single threaded language, lets go
@@zeez7777 race conditions happen all the time in single threaded languages, its called asynchrony... and setTimeout is a classic culprit
@@Iriscgldom What you're talking about are not real race conditions. Race conditions can only happen if you have atleast 2 threads. Event loop screw ups are similar but not race conditions.
What happened before let?
So let is captured using copy and var is captured using closure?
I've been programming my whole life and this is the first time I ever seen the pratical difference between "var" and "let". I have never seen a need for "var" anyhow.
Yeah there isn't really any need for var anymore. But I think understanding the difference is somewhat important because of how many resources online still use var.
@@ConnerArdman True. Good example.
So does let create a copy backed by a function scoped variable? Or initialize the variable on each run? Otherwise how do you keep the state over each iteration?
Let is block scoped. In the case of a for loop, it creates a new variable for each iteration, since each iteration is treated as its own block.
Had a similar issue with fade function of jquery, had some divs that were numbered, everytime I removed one of these divs I had to reorder the numbers but because of fade the reorder happened before the deletion and messed up everything.
My man Akshay Saini made me powerful enough to understand it
This is why c++ capture groups are so superior
it should be mentioned to new devs that this is generally not a good practice. `var i = 0` is now a globally available variable and may cause unintended side effects. the general rule: use `const` 98% of the time and use ‘let’ only if you’re mutating data. keep `var` in the trash where it belongs.
now the real question is in which scenario i will ever find myself using this function?
JS is freakin chaotic: const const 2 === const 2 is false but its true for == iirc. Const pointer and all makes sense sure, but its one the most syntactially convoluted things that is so wide spread.. the antithesis to python basically
I didnt know this... i only ever use let before
Good, c# do this too. seems theres no let in c#
when I set the 2nd argument of setTimeOut to 0 it still prints 3 3 3
Yeah this is due to the event loop in JavaScript. setTimeout calls an API that essentially just delays the execution of the code by a minimum of whatever delay you set, even if it is 0. However after that delay completes, the code does not immediately run. Instead, it is just queued up in what we call the callback queue (or sometimes called the task/message queue). This is because JavaScript only has a single thread, so the other code that is currently running must complete before the setTimeout callback can be executed. Once all of the other code finishes executing (i.e. the call stack is empty), then whatever code is at the front of the callback queue can finally run.
So if you do setTimeout(callback, 0), the callback does not run immediately. It runs after all of the other code completes. In this example, that means it has to wait for the for loop to complete, thus giving the same output of 3 3 3.
@@ConnerArdman Thank You for the explanation
Why does 'i' reach 3? Doesn't the loop increment 'i' to 2 only?
I still didn't quite understand why var "i" has only 1 "i" and let has 3 "i". I mean isn't there only 1 memory allocation in the stack for "i" and the same "i" keeps getting updated in both cases?
Sort of. The experience the language gives you is essentially what you are describing, but it is not actually the same i every iteration with let. It is a new one being created based on the value of the previous iteration's i. Pasting this explanation from an earlier comment I wrote:
This might seem contrary to how the code looks, but this is how the specification is defined, because let is meant to be block scoped. What the JS engine does under the hood for each subsequent iteration when using let is very roughly something like this:
1. Create a new variable environment.
2. Duplicate the iteration variable from the previous iteration's environment into that new environment.
3. Run the increment code on that copy of the iteration variable.
4. Do whatever's inside the for loop.
5. Repeat until the loop condition is false.
Here's the extremely difficult the read specification detailing this (10/10 don't recommend actually trying to read it all, but it's interestingly nonetheless):
262.ecma-international.org/6.0/#sec-for-statement-runtime-semantics-labelledevaluation
@@ConnerArdman Thank youuu
Bro I learned JS like three days ago and I got this right.
Rust compiler would not even allow this bullshit1!
Amen!
The Rust compiler allow this and the program would print 012 in an equivalent situation as there are no implicit references
This only works in "for (of)". In "for (;;)", the initial "let i = 0" is scoped for the entire loop. You need to copy i in a local variable of the iteration, for exanple "let j = i" between the first and second lines, otherwise you get the same problem as using var.
I had a problem like this when I wanted a few divs to fade in fade out in a specific order and they all just flashed at the same time.
I ended up giving it by putting it in a asynchronous function but I still don't understand why it happens and why the synchronous function helped
And at the end of the function, out of the perenthesis I had to put I,100
Don't know why
can anyone explain the concept of fuction and block scope in this context? "We have a different i for each iteration". Okay, but how doest it gets updated then? On the new iteration, there is a new i and it should be 0 again. I'm sororry if this sounds dumb)
var is function scoped. So the var while loop equivalent is roughly this (resulting in only one i ever):
function foo() {
i = 0;
while (whatever) {
// do stuff
i++;
}
}
let is block scoped. Since loops are blocks, we get a new i for each iteration. But this doesn't restart at 0, it just uses the previous value. This is a bit harder to show with equivalent code, because a lot is happening under the hood to make it work. But generally speaking, it will result in something like this at the end of each iteration:
newi = i + 1
delete i
i = newi
@@ConnerArdman didn't expect that I would get an answer at all) thank you!
Regrets after interview this question was asked me today in my interview and unfortunately not able to answer in case of var
use let and const in up todays development pls
What would const i = 0 do?
I just would not apply to a place still using Javascript when most of the frameworks are trying their level best to be Typescript first
What if we want to only use var and achieve the same thing without using let or const 🤔🤔🤔
and what was the question?
I just started learning about JavaScript, stuff like this scares me but it also makes me curious. This doesn’t seem like a real useful problem to solve (more of a fuck you problem to test if you are that much more aware of what is actually happening), as you mentioned in the video if you used let instead of var everything would be working as expected, so I just ask myself why use var in the first place. To me programming feels like you need to learn what could fuck you over so you don’t get fucked over.
Yeah it’s more of just a test of if you know the “why” for common practices. There’s really no reason to use var anymore essentially for this reason.
100% have seem this at work and with student projects. Just replace the timeout with any HTTP call.
How to know you are about to work in a legacy code base in an interview.
This is a trivia question, not an interview question
Yeah so important to know that in your crud apps ;D
This would be WAY easier to explain with a simple 2-column chart.
Variables | value
i 3
And so on.
Leave out the jargon. Just say... "this one creates only one variable"
"this one creates 3"
I like his cadence... Slow teachers are hard to understand.
I interviewed for Angular position and the interviewer asked me only console.log outputs. One of them was this. I am sure he copied it from here 😅
I don't get where would I do this in a real world scenario?
There’s not a single good reason to use var since ES6 came out
Yeah this makes absolutely zero sense if you don't know anything about coding.
The RUclips Shorts recommendation system went kinda rogue on this one 😂
@@ConnerArdman, FrontendExpert is brilliant. Thank you for that.
Never use var use let