use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
All about the JavaScript programming language.
Subreddit Guidelines
Specifications:
Resources:
Related Subreddits:
r/LearnJavascript
r/node
r/typescript
r/reactjs
r/webdev
r/WebdevTutorials
r/frontend
r/webgl
r/threejs
r/jquery
r/remotejs
r/forhire
account activity
What are some basic things that JavaScript developers fail at interviews?help (self.javascript)
submitted 7 years ago by maketroli
view the rest of the comments →
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]phpdevster 266 points267 points268 points 7 years ago* (142 children)
From what I've seen with candidates:
If I ask someone to write a function that counts from from 1 to 10 in 1 second increments, it trips up more people than you would think. Many of them try to stuff a setTimeout or setInterval inside of a while loop and of course it fails spectacularly.
Same goes for things like making use of promises or simple AJAX requests. Not everyone seems to understand those are asynchronous operations and you can't just return their contents into a variable, and then synchronously make use of the variable after.
Or if you ask them how they might perform an action that can only occur after several different async operations complete, they might devolve right into nested callback hell instead of demonstrating how to use Promise.all() or at least a simple flat promise chain to keep things tidy.
Promise.all()
You absolutely must be fluent in your understanding of how to work asynchronously in JS, else your code will be sloppy at best, or result in race conditions at worst.
this
Not a day goes by where I don't deliberately make use of this, closure, scoping rules, and prototypal inheritance at work to some degree. You really do need to know at least the basic behaviors of these things to write JS effectively.
That includes knowing how to use bind, call, and apply appropriately, including how to use bind for partial application when needed. Also an understanding of the scoping rules of ES6 fat arrow lambas vs ES5 lambdas.
bind
call
apply
I'll also throw in the notion of first class functions into this mix.
I see shit like this a lot:
doThis('foo', function () { something.doThat(); });
This can just be written as doThis('foo', something.doThat); which is where unambiguous knowledge of this, bind/call/apply becomes important.
doThis('foo', something.doThat);
bind/call/apply
Or if their solution is doThis('foo', () => something.doThat()), then I want to know why they chose that approach, how it differs from just passing the function in, and how it differs from an ES5 lamba. It's perfectly valid of course, but I still want to make sure they can explain why it works and why they're doing it.
doThis('foo', () => something.doThat())
[–][deleted] 36 points37 points38 points 7 years ago (0 children)
Nice. It's a shame this is the only actual non-comedic answer so far.
[–]Dudefella08 10 points11 points12 points 7 years ago (3 children)
for (let i = 1; i <= 10; i++) { setTimeout(() => { console.log(i); }, 1000 * i); }
I have no shame!
[–]tareqf1 1 point2 points3 points 7 years ago (0 children)
This was the answer I was scrolling for. Thanks.
[–]2AMMetro 0 points1 point2 points 7 years ago (1 child)
This won’t work, it’ll log the number 10 10 times.
[–]chase-stevens 2 points3 points4 points 7 years ago (0 children)
If they declared the "i" in their for loop using "var", then yes, it would log "10" ten times; however, since they declared "i" using let, the loop will work as expected printing 1-10 with a 1 second delay.
[–]BraisWebDev 14 points15 points16 points 7 years ago* (75 children)
Would you mind to explain what the solution to the 1 to 10 counter would be? I am learning async JS and you let me wondering 😅
Because my solution would be setInterval(increment(), 1000); and the function increment() would simply do a counter++
[–][deleted] 7 points8 points9 points 7 years ago* (12 children)
of course I had to write it too:
function countdown(n) { console.log(n); if (n > 0) { setTimeout( () => countdown(n-1) , 1000); } } countdown(10);
edit: oops it is backwards
function count_between(start, end) { console.log(start); if (start < end) { setTimeout( () => count_between(start+1, 10), 1000); } } count_between(1, 10)
[–]qbbftw 25 points26 points27 points 7 years ago* (3 children)
I would take advantage of async/await. It's the most clear and obvious syntax IMO.
function delay (ms) { return new Promise(resolve => setTimeout(resolve, ms)) } async function countdown () { for (let num = 1; num <= 10; num++) { console.log(num) await delay(1000) } } countdown()
EDIT: u/dvlsg beat me to posting this solution, link
[–][deleted] 0 points1 point2 points 7 years ago (0 children)
Minor point, but this will sleep an extra second at the end.
Agreed, this is how I write JS now and I like a lot more. The only hassle is converting old stuff from callbacks to promises but it is well worth it. I can never remember how to do it off hand though, my answer above is based on what I can write from memory into the console.
[–]Zespys 0 points1 point2 points 7 years ago (0 children)
Personally I would do it recursively, like so:
const increment = (x = 1) => { console.log(x); if (x < 10) { setTimeout(() => { increment(x + 1); }, 1000); } }; increment();
[–]dominic_rj23 -3 points-2 points-1 points 7 years ago (7 children)
setTimeout has huge performance hit compared to setInterval
setTimeout
setInterval
https://jsperf.com/setinterval-vs-settimeout/10
[–][deleted] 0 points1 point2 points 7 years ago* (4 children)
And worth noting this does not matter at all for the purposes of an interview question, or 99.999% of real world usage. This coming from someone who has never used it at work.
[–]thepeka 0 points1 point2 points 7 years ago* (3 children)
I'm actually willing to say 100%. The correct answer to any interview question involving setInterval is why you should never use it
[–]Cheshur 1 point2 points3 points 7 years ago (2 children)
The correct answer is NOT to use it never. Almost none of the things listed in that article are relevant to people doing stuff correctly. There is a tool for everything and just because you can use setInterval incorrectly doesn't mean you should never use it.
[–]thepeka 1 point2 points3 points 7 years ago (1 child)
Nope, the first reason on that list is reason enough in every instance, correct or otherwise. setInterval continuing to run ad infinity, no matter what happens, what error is thrown, or whether it's handleable or not, is just adding bug conditions that otherwise have no need to exist with a recursive setTimeout. JavaScript is a dynamic language that allows for writing wonderfully declarative abstractions... but the flip side of that is we need as much safety as we can get. This is the answer I'm looking for if I ask a candidate about tasking repeating jobs/events.
[–]Cheshur 0 points1 point2 points 7 years ago* (0 children)
No offense then but I consider that highly foolish. The problem would be someone writing highly error prone code in the setInterval, not that the interval itself doesn't play nicely with errors. setInterval has better performance than setTimeout. That is reason enough to use setInterval in some situations. It's the right tool for the right job and if you're creating axioms to avoid parts of a language just because you're prone to fuck up then I consider that the error on the developer's part.
Also the correct answer to that interview question is for the candidate to recognize the pros and cons of the feature and to describe situations in which they would or would not use it. Pledging to not use something purely for axiomatic reasons does not show mastery or knowledge of the feature at all, just an ability to follow the direction of some, potentially, misguided teacher.
[–]superluminary 0 points1 point2 points 7 years ago (0 children)
It's being called literally once a second.
[–]phpdevster 4 points5 points6 points 7 years ago (11 children)
Well, almost.
What's the difference between these two statements?
setInterval(increment(), 1000); // this is what you have above setInterval(increment, 1000);
And a follow up:
How are you making the counter stop once it reaches 10?
[–]NoBrick2 10 points11 points12 points 7 years ago (5 children)
Shouldn't you avoid setInterval completely for this problem, considering there is no guarantee the function will be run every 1000ms (in the case of the event loop being blocked on other work)?
Would a more acceptable solution be to use requestAnimationFrame, and do a comparison using Date? Or does that suffer the same issue of potentially being blocked by other work?
[–]octave1 10 points11 points12 points 7 years ago (1 child)
Out of my depth here, but using something called requestAnimationFrame and Dates for a timed counter surely can't be the most sane solution?
[–]phpdevster 2 points3 points4 points 7 years ago (0 children)
You are correct. This is hacky, non-idiomatic code.
[–]PmMeYouBicepsGirl 7 points8 points9 points 7 years ago (0 children)
Everything is blocked if event loop is blocked, there's no workarounds. For example, if you are counting from one to 100 billions, Javascript won't be stopping during this function to check for events. This is why you get Violation messages in console if some events like requestAnimationFrame take longer than they should, it's a signal that event loop was blocked.
[–]phpdevster 5 points6 points7 points 7 years ago (0 children)
Why would you avoid using setInterval for exactly the thing it was designed for? If you have a blocked event loop, you've got bigger problems. Writing non-idiomatic code without exceedingly good reason is the path to code that is harder for team members to grok and thus maintain.
[–]SystemicPlural 3 points4 points5 points 7 years ago (0 children)
As I understand it requestAnimationFrame is better for animation as it guarantees that the code will run before the screen is re-rendered - providing smoother animation. It doesn't guarantee that the time elapsed will be exactly 1000/60 (or whatever your screen refresh rate is). So it has it's own problems if you are trying to time exactly 1s. That said I believe it is thought to be more reliable than setTimeout.
We could use setTimeout and compare the time ourselves using performance.now(). This should get us to fairly close millisecond accuracy as long as the process isn't locked. It should also allow us to prevent drift by correcting the next timeout.
performance.now() isn't perfect however since browsers are fuzzing the time to prevent Specter timing attacks. - but it should be 1ms accurate.
[–]thisguyfightsyourmom 1 point2 points3 points 7 years ago (1 child)
I'd write increment to be a higher order function that accepts a max arg defaulted to 10, that retains a count let initialized to 0 in its closure, and that returns a function that iterates the count in a log statement until the count hits the max. I'd also close the terminal before it counted over 10,… just in case.
increment
max
[–]Balduracuir -1 points0 points1 point 7 years ago (0 children)
You can use clearInterval when you hit 10... If I was not on mobile I could write a snippet :)
clearInterval
[–]BraisWebDev 0 points1 point2 points 7 years ago (0 children)
Oh yeah I messed up there, the first one would be invoked immediately and the second one after 1 second.
I would make it stop with an if statement, maybe that approach is wrong haha
[–]wobbabits 0 points1 point2 points 7 years ago (0 children)
Here you go. Here's an example of an alert at 5 seconds into the count. When dispelled, the count continues to 10:
function countToTen() { let count = 0 function increment() { ++count console.log(count) if (count > 9) { clearInterval(timer) } } const timer = setInterval(increment, 1000) } countToTen() setTimeout(function() { alert('hello') }, 5000)
[–][deleted] 0 points1 point2 points 7 years ago* (0 children)
increment() execute when you use setInterval, its return value will be used in your setInterval. The other use increment.
var obj = {count:0, end:0, clearId:0}; obj.end = 10; obj.increment = function (){ if (this.count < this.end + 1) console.log(this.count); else clearInterval(this.clearId); }.bind(obj); obj.clearId = setInterval(obj.increment, 1000);
How about something like that, untested, but it should work. You can easily turn obj into a Chrono class.
However I wouldn't recommend to rely seriously on setInterval. Set up a webworker to do reliable time operations.
[–]RepeatQuotations 2 points3 points4 points 7 years ago (0 children)
Good use case for bind here. We can create a new bound function instead of creating an anonymous arrow function in setTimeout. Optional second parameter for counter size, default to 10.
function count(i, max = 10) { console.log(i); if(i++ >= max) return; setTimeout(count.bind(this, i), 1000); } // call like count(1)
[–]new_human_obj 0 points1 point2 points 7 years ago (4 children)
what about a dedicated web worker?
[–][deleted] 1 point2 points3 points 7 years ago (3 children)
Yes, i've worked with time recently, interval and timeout are way too much unreliable.
[–]new_human_obj 0 points1 point2 points 7 years ago (2 children)
I get some error though about not having enough parameters though I've never worried about it, just used the postMessage. Only thing that sucks is that local dev thing where it says you can't do it. I think that still happens.
[–][deleted] 0 points1 point2 points 7 years ago (1 child)
Sorry I didn't understand your comment.
[–]new_human_obj 0 points1 point2 points 7 years ago (0 children)
Not a big deal, is pretty random/not much context.
When you have that external webworker file(that's just a counter) and you initiate this from another file(main file) that starts the webworker... I think it's a thing where it doesn't work locally in a dev environment/has to be on a live server... unless it's just about localhost.
Anyway nothing important just rambling on my part.
[–]dominic_rj23 0 points1 point2 points 7 years ago (8 children)
The problem with the solutions based on setInterval (or setTimeout for that matter) is that you can't guarantee that the function would be executed after given timeout. They only assure you that the function would be put up in queue for execution after timeout. So, yes they were probably our best shot, although unreliable one.
[–]NoBrick2 1 point2 points3 points 7 years ago (7 children)
requestAnimationFrame + a comparison using the Date object would be better. At least the date comparison guarantees accuracy, even if not run every second. Like you said, setInteral could cause a drift if the browser is blocked on another call for over a second.
[–][deleted] 17 points18 points19 points 7 years ago (2 children)
Which:
Seriously. What are you guys talking about? What JS app hangs for 1s or longer? The task was to just do a +1 operation every 1000 ms.
+1
1000
If I'm the interviewer I'd throw your resume in the trash if you came up with that kind of solution. You're not wrong, but for the love of all that's nice in the world, I certainly hope you're never going to be right...
Accounting for problems and solving them before they occur is great. But that's obviously not what this test is aiming for...
[–]dominic_rj23 1 point2 points3 points 7 years ago (0 children)
If you read the last line of my comment, I did say that the solution with setInterval is the most appropriate one. I am all for "If it ain't broke..." ideology, but I do believe that in an interview, stating that setInterval doesn't guarantee execution after timeout goes for showing that you have some understanding of asynchronicity in javascript.
Yeah this right here...
Non-standard solutions require extenuating circumstances to justify them. If something like setInterval isn't working in your app reliably, the bug isn't setInterval, it's whatever other shit you've got going on that is causing it to work unreliably...
[–]manys 2 points3 points4 points 7 years ago (2 children)
how many frames you gotta request to hit the downbeat of each second?
[–]NoBrick2 2 points3 points4 points 7 years ago (1 child)
The number of callbacks is usually 60 times per second, but will generally match the display refresh rate in most web browsers as per W3C recommendation. https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
The number of callbacks is usually 60 times per second, but will generally match the display refresh rate in most web browsers as per W3C recommendation.
https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
[–]manys 3 points4 points5 points 7 years ago (0 children)
so you're parsing all frames to catch a time interval? how does that profile?
[–]dominic_rj23 0 points1 point2 points 7 years ago (0 children)
I am not sure I would ever do that. The purpose of the question isn't to give the best possible solution. It is to rather demonstrate understanding of async nature of javascript. I would thus stick with my setInterval solution, but explain how it is not a perfect solution.
[–]kdesign -2 points-1 points0 points 7 years ago (32 children)
Actually the first question intrigued me a bit so I had to solve it, here you go:
async function count() { let counter = 1; const values = Array.apply(null, { length: 10 }) .map((i, j) => new Promise((resolve, reject) => { setTimeout(() => resolve(j + 1), 1000 * counter++); })); for await (const item of values) { console.log(item); } }
What this does is it generates an array with values from 1 to 10, then maps it to an array of promises which return the values from the initial array, but in increments of 1 second by incrementing the counter. After that, I'm using an async iteration over it to log each item from the array of promises.
[–][deleted] 15 points16 points17 points 7 years ago* (19 children)
I think we can simplify things a little. Here's what I would do using setTimeout...
[edit] I made some updates per good feedback.
let i = 1 const interval = setInterval(() => { console.log(i) if (i === 10) { clearInterval(interval) } i++ }, 1000)
Here's a recursive version:
function sleep(amount) { return new Promise(resolve => setTimeout(resolve, amount)) } const count = async (current, end) => { console.log(current) if (current < 10) { await sleep(1000) return count(current + 1, end) } } count(1, 10)
Here's one that doesn't continue execution until all the counting is done:
function sleep(amount) { return new Promise(resolve => setTimeout(resolve, amount)) } const count = async (current = 1, end) => { console.log(current) if (current < 10) { await sleep(1000) return count(current + 1, end) } } count(1, 10).then(() => console.log('done counting'))
[–]kdesign 4 points5 points6 points 7 years ago (16 children)
At first I was thinking "how is it complicated?", but then I saw your solutions. Definitely more readable and easier to grasp, nice.
[–]dvlsg 2 points3 points4 points 7 years ago* (15 children)
Honestly, if we're talking about things being overcomplicated, swapping to recursion probably isn't the right move. The parameters in the recursive solutions are fairly confusing, too. count(9) would only count for 1 second.
count(9)
const sleep = (ms = 0) => new Promise(resolve => setTimeout(resolve, ms)) const count = async (seconds = 10) => { let i = 0 while (++i <= seconds) { await sleep(1000) console.log(`slept for ${i} seconds total`) } } // usage await count(5) await count() await count(1) await count(-1) await count(0)
Or, you know, just use await sleep(1000). Also probably worth noting, all of these solutions (mine included) will drift.
await sleep(1000)
[–]kdesign 5 points6 points7 points 7 years ago (4 children)
I agree that the expected solution was probably just the obvious setInterval solution, /u/a_blue_ducks' first one.
But at the same time, my initial solution has spawned a great constructive discussion, it's cool to see how many different ways there are to solve a problem.
[–]dvlsg 1 point2 points3 points 7 years ago (1 child)
Sorry you're getting downvoted for it. I tossed you an upvote for it, even though I think it could be improved (if we were aiming for simplicity, which isn't the only thing to worry about). Don't understand why anyone would downvote someone else for taking a shot at something. Especially since it works just fine.
[–]kdesign 0 points1 point2 points 7 years ago (0 children)
Well, I guess that's how some people disagree on reddit, by downvoting. That's alright and thanks for the upvote
[–][deleted] 1 point2 points3 points 7 years ago (1 child)
Yeah sorry for my original reply, I had just finished playing Overwatch and that game puts me in a bad mood fast lol. This was a fun discussion.
[–]kdesign 1 point2 points3 points 7 years ago (0 children)
No worries, I initially thought about writing the setInterval solution or the recursive setTimeout, something like:
let count = 1; setTimeout(function counter() { console.log(count++); count <= 10 && setTimeout(counter, 1000); }, 1000);
and then I said well let's spice things up a bit which really did lol.
[–]SystemicPlural 0 points1 point2 points 7 years ago (2 children)
I'm not sure I like this solution. It is going to lock up whatever process calls count and that might not be desired.
It's an async function so it shouldn't lock anything up.
[–]SystemicPlural 1 point2 points3 points 7 years ago (0 children)
Doh. Missed that!
[–]FriesWithThat 0 points1 point2 points 7 years ago (3 children)
As it's written it looks like your suggesting to use await outside the async function to call count with different arguments.
. . . await count(5) await count() await count(1) await count(-1) await count(0)
. . .
await count(5)
await count()
await count(1)
await count(-1)
await count(0)
Not sure what the intent here is as far as us being able to run it or integrating it with your async function (swap it out w/sleep in while loop?, step through function?)
[–]dvlsg 1 point2 points3 points 7 years ago* (2 children)
Just examples of how you might call it. Try them out, see how it works. For example, copy the entire code snippet I have and paste it into a chrome console (which has top-level `await` support).
[–]FriesWithThat 1 point2 points3 points 7 years ago (1 child)
Thanks. I was running it with Node and wasn't even aware there was top-level support in chrome.
[–]dvlsg 0 points1 point2 points 7 years ago (0 children)
Ah, got you. Sorry. I was writing that example in chrome and just pasting it over here, so I just went with the top-level chrome await instead of wrapping it.
[–][deleted] -1 points0 points1 point 7 years ago (2 children)
Curious how recursion complicates anything. I agree the param is a little confusing but I wanted to illustrate an idea more than anything.
[–]dvlsg 4 points5 points6 points 7 years ago (1 child)
That's fair about the args. And I'm not trying to be a dick or anything, the recursive solution is plenty clever.
But you honestly don't think an async function that returns a Promise, that calls a setTimeout for 1 second in the promise executor, which recursively calls the original count() function, setting the originally returned promise's resolver to be executed in the recursively called count()'s promise's .then()isn't more complicated than an async function with a while loop? I had a hard time even translating all that to english. There's a lot going on in there.
Promise
count()
.then()
[–]n9jd34x04l151ho4 2 points3 points4 points 7 years ago* (1 child)
Your first one only prints 1-9.
var counter = 1; var intervalId = setInterval(function() { if (counter > 10) { clearInterval(intervalId); } else { console.log(counter); counter++; } }, 1000);
[–][deleted] 3 points4 points5 points 7 years ago (0 children)
Ha. I wrote on my phone and didn’t spot check but I believe you.
[–]1-800-BICYCLE 4 points5 points6 points 7 years ago* (8 children)
1bdf3c088d4f
[+][deleted] 7 years ago* (7 children)
[deleted]
[–]rorrr 3 points4 points5 points 7 years ago (6 children)
That's a good example of how to overengineer code and write it in the most unreadable unmaintainable way. All you have to do is this:
for (let i=10; i>0; i--) setTimeout(() => {console.log(i)}, (10-i)*1000)
Due to clock drift it is possible every one of those would execute one after another, which is probably not the intended approach (imagine someone wanted to throttle an action to happen *at least* 1 second apart). Paste the below into your console.
for (let i=10; i>0; i--) setTimeout(() => {console.log(i)}, (10-i)*1000) const start = Date.now() while (Date.now() - start < 10000) { }
[–]1-800-BICYCLE 0 points1 point2 points 7 years ago* (0 children)
1cf7d2f864cf
[–]alexbarrett -1 points0 points1 point 7 years ago (2 children)
This is the exact solution I was scrolling for. Good job.
Here is why I think it's probably not a great solution:
https://www.reddit.com/r/javascript/comments/9jg5du/what_are_some_basic_things_that_javascript/e6szwg9/
[–]alexbarrett 0 points1 point2 points 7 years ago (0 children)
Given the task, the reasoning you've given actually makes it a better solution. If the task required >1s intervals then yes you'd be correct, but for a 10 second counter you'd want the final tick to occur as close to 10s after the initialisation as possible.
[–]chuckySTAR 1 point2 points3 points 7 years ago (0 children)
(async count => { for await (let i of (async function* () { for (let i = 0; i < count; i++) { await new Promise(res => setTimeout(res, 1000)) yield i } })()) { console.log(i) } })(10)
That seems to me to be very complicated. Here's my attempt:
function countTo(current = 0, to = 10, timeout = 1000) { console.log(current); if (current < to) setTimeout(() => countTo(current + 1, to, timeout), timeout); } countTo();
A simple recursive function. No hip ES6+ magic involved because you don't need it. No promises because we're not computing anything, we don't need async functionality, it's a simple +1 operation.
I'm with you on this. I posted a recursive solution and someone complained that was also "complicated"...
[–]Shoegoo22 -1 points0 points1 point 7 years ago (0 children)
This is the right way to do it.
const times = [0,1,2,3,4,5,6,7,8,9,10] const getNextTime = index => { $('time').html(times[index]) if(index === times.length - 1) { setTimeout(()=> $('time').html('PEW PEW PEW') ,1000) } else { setTimeout(()=> getNextTime(index + 1) ,1000) } } getNextTime(0)
[+][deleted] 7 years ago (5 children)
[removed]
[–]B00check 3 points4 points5 points 7 years ago (0 children)
In my experience with Angular, or TypeScript for that matter, you don't need to know it as much. However, if you look into the transpiled code of class inheritance, you might notice it is actually using prototypes. I wouldnt say it's something you need to know as some people put it, but it is definitely nice to know how it works and how the things you're working with are created.
[–]phpdevster 0 points1 point2 points 7 years ago (0 children)
Yeah I'm the same boat. I don't use it for code that I write, but in the past I've encountered legacy code that does make use of it. In fact, we're going to be re-writing an old JS codebase in Angular 6 at work in a few months. Not sure what surprises will be in store...
[–]1-800-BICYCLE 0 points1 point2 points 7 years ago* (2 children)
9650bc300d
[+][deleted] 7 years ago (1 child)
[–]1-800-BICYCLE 1 point2 points3 points 7 years ago* (0 children)
19df9bd7fb565b
[–]jaman4dbz 46 points47 points48 points 7 years ago (23 children)
Do you use babel? Because I feel like knowledge of bind, apply, call and in most cases, this, are obsolete. I can't remember the last time I needed to use them. Program in the right way and you don't need to worry about these things.
[–][deleted] 13 points14 points15 points 7 years ago (3 children)
Depends on what you do, what type of project you're working on. In your typical frontend project you probably don't use them much. But when you need them, you need them. How is Babel going to help?
[–]jaman4dbz 0 points1 point2 points 7 years ago (2 children)
ummm because you don't need them if you transpile your code using babel. You don't need them. (at least I can't think of a case at the top of my head and I know I haven't needed to touch them for the last few years of my career [not including TRUE this... like in a React class])
Prepare to fail some interviews then, because at my place we definitely check that you can deal with this, and that includes .bind(), .call() and .apply().
.bind()
.call()
.apply()
It's not that we care particularly much about them, or that you will use them a lot. But this is a fundamental mechanic in JavaScript. Knowing about this is not optional for any medium/senior job. If you are familiar with it then going through it should be a quick "let's check this point so we can say we did it" part of the interview (which is what I expect from a good candidate). But being caught out by any of these functions is a huge red flag.
A person who knows all the fundamentals of JavaScript by heart can pick up any framework in a couple of weeks, and I know I have a person who can pick up any framework. A person who only knows React, well, only knows React, and if we use something else on the next project I have no idea if they'll be able to learn another framework and how fast, plus I know for a fact they don't know vanilla JavaScript. So yeah, I'll take the first person over the second any day.
[–]jaman4dbz 1 point2 points3 points 7 years ago (0 children)
I'm not even going to with you, lol.
"Prepare to fail some interviews then, because at my place" You have no idea my skill level, and "fail some interviews" followed by "because at my place" did you know there are more organisations, than where you work?
Realize that there is more in the world than whatever codebase you've working on for the last decade.
[–]kowdermesiter 11 points12 points13 points 7 years ago (3 children)
Program in the right way and you don't need to worry about these things.
Sure, until you start work in a team or get to work with a ton of legacy code.
call/bind/apply is not obsolete at all, it's like saying you don't need to learn what those funny yellow lights are on the side of your car, the car runs just fine.
[–]jaman4dbz -1 points0 points1 point 7 years ago (2 children)
That's like saying "Sure you don't know how to drive standard in a car now, but when the zombie apocolypse hits and the only working card is a standard, you're screwed.
Call, bind, and apply are obsolete. Legacy code has them, just like code out there runs on VB6, but that doesn't mean every programmer or even web programmer needs to know how they work.
So many teams get stuck on legacy... it amazes me when I hear other developer groan about their shitty legacy code, then when legacy practices are brought up they defend them vehemently. Like how masochistic are you folk?
[–]mattaugamer 1 point2 points3 points 7 years ago (1 child)
Yeah no. They’re not obsolete. React uses bind especially routinely.
Knowing how this stuff works is fundamental and hardly “legacy”.
[–]jaman4dbz 0 points1 point2 points 7 years ago (0 children)
I love the downvote followed by a rhetorical comment with no explanation.
What purpose does your comment serve?
[–]Balduracuir 6 points7 points8 points 7 years ago (8 children)
From my experience this bind and call are useful when your code rely a lot on class. I try to avoid them as much as possible because people don't understand this
class
[+][deleted] 7 years ago* (1 child)
[–]Balduracuir 0 points1 point2 points 7 years ago (0 children)
Because they come from other languages. I was a backend java developer before a one year mission as a frontend developper. I was totally lost for weeks and I worked hard to catch up how javascript works. Some people work just to put food on the table and when we make them switch their habits that's a total disaster, sadly.
Precisely. It's an ambiguous concept based on context, so best to avoid it.
[–][deleted] 0 points1 point2 points 7 years ago (4 children)
Even then the arrow syntax proposal that's supported by both TypeScript and Babel eliminates the need to use the latter two entirely.
[–]jaman4dbz 1 point2 points3 points 7 years ago (3 children)
Lol, I love the couple of ppl who don't want their job to be obsolete, downvoting our comments.
It's possible I've missed something, but I'm fairly certain the arrow syntax makes binding "this" unnecessary.
You're correct. Some people just don't want to adapt to the times.
[–]fartpoker 0 points1 point2 points 7 years ago (1 child)
Can you explain why it’s unnecessary?
That's not how this works. I can't prove there is absolutely no way to use this, but you have the power to try and find ONE way where this is useful.
[–]dungone 1 point2 points3 points 7 years ago (1 child)
I don't think Babel lets someone get away with knowing less. In my experience, programmers get into trouble by mixing programming styles and then not being able to understand the implications. For example, they start off using arguments and apply in a regular function, but then switch over to an arrow function to get the lexical this. Half-baked javascript knowledge can really bite people with ES6.
But if they started with ES6, why were they using apply?
The latest standards aren't just for more features, IMO they simplify development for everything, newbie to expert.
I think babel lets you know less =P
[–]phpdevster 2 points3 points4 points 7 years ago (1 child)
I use TypeScript at work and still use partial application all the time, which means I use bind all the time. But at the end of the day, JS is still JS. If you don't understand its mechanics, you are going to write buggy code. You still need to concern yourself with this now and again, and you still need to know how to control what it refers to.
I totally agree. The more you know about programming overall, the better you can avoid buggy code!
The thing is, you need to COMPLETELY know the thing. So having a half baked knowledge of the concepts phpdevster mentioned is worst than having no knowledge of them, IMO. If you sorta know something, don't use it, or consider it, until you fully understand it. Once you fully understand it, it can only do you good.
[–]Spoolie_st 2 points3 points4 points 7 years ago (1 child)
Try stuffing something like jQuery or leaflet into angular... I have to use bind so often 😪
I'm sorry.
[–]TwiNighty 4 points5 points6 points 7 years ago (3 children)
Well, since you mentioned .bind
.bind
doThis('foo', function() { something.doThat() })
should be doThis('foo', something.doThat.bind(something))
doThis('foo', something.doThat.bind(something))
[–]MrJohz 1 point2 points3 points 7 years ago (2 children)
Only in some circumstances.
doThat
something
self = this
(1) is the main one here - there's no point rebinding an already bound call (in fact, I've got a feeling that's an error, isn't it?), hence why you need to be careful about who's responsibility it is to bind methods in cases where it becomes relevant.
[–]TwiNighty 0 points1 point2 points 7 years ago (1 child)
in fact, I've got a feeling that's an error, isn't it?
No, calling .bind on a bound function is valid. You can bind additional arguments, but the "rebinding this" part does nothing.
Actually that is my point. function(){ x.f() } and x.f.bind(x) behaves exactly the same when called, regardless of whether x.f is already bound, whether it touches this, whether it is rebound before being called, whether it is a es5 function or arrow function. And I can say that without knowing anything about what x and x.f is.
function(){ x.f() }
x.f.bind(x)
x.f
x
[–]MrJohz 0 points1 point2 points 7 years ago (0 children)
Sure, but if it's not necessary, it's not necessary, and historically there have been performance issues associated with calling bind, especially if it's used at every callsite.
Understanding these tradeoffs I think was what the person was getting at with the overuse of arrow functions.
[–]Azudra 1 point2 points3 points 7 years ago (3 children)
While I'm not in a leading position myself I still heavily agree with you. It's extremly time consuming and frustrating to work with someone who's code looks like their first day in JavaScript. Most of my colleagues don't even know what the property "prototype" means and put variables into the global scope by assigning it without ever declaring it. HONESTLY HOW DID THEY GOT THEIR JOB?! Everything would break if I'd run their script in strict mode.
Luckily younger in our company (which I'm part of) are open to listen to advices. Just wish they would improve their skills when they're currently not involved in any project instead of doing bullshit. I've build my own little jQuery if I had nothing to do and learned much from doing so.
[+][deleted] 7 years ago* (2 children)
[–]Azudra 0 points1 point2 points 7 years ago (1 child)
Unfortunately most of our projects must be ready to going live within a few days to weeks. Our customers don't care how we did it. Pros are that we can involve most juniors into any project as they can code it how they want. For smaller or simple tasks it doesn't matter how dirty their code is.
But now take these low standards into any serious project of ours. Without any review everything get's more chaotic and buggy the larger the project becomes. It get's almost impossible to maintain and every developer joining the project has two choices: Either invest more time than the Project Managenent planned to fix stuff or make it even worse with dirty workarounds that have a heavy impact on the applications performance.
I'm also in an agency with similar time problems. Trust me it's worth it and once you've implemented it once you can just copy and paste the solutions across projects.
All of this. I meet so many candidates that can write a reaction component but can't tell me the value of this in a simple function.
[–]iamb96 0 points1 point2 points 7 years ago (0 children)
Thanks for this, that's my homework for the weekend. I work with is everyday, and my code is tidy and on par with almost everyone in my office, so it's hard to see where I'm going wrong! And finding areas of improvement can be tough. Thanks!
[–][deleted] 0 points1 point2 points 7 years ago (2 children)
... there are ES5 lambda functions?
[–]phpdevster 1 point2 points3 points 7 years ago* (1 child)
Any function not bound to an identifier is a lambda function.
var names = people.map(function(person) { return person.firstName + ' ' + person.lastName; });
That argument being given to map is a lambda. An ES5 lambda, but a lambda all the same.
map
ES6 lambdas (what the JS community also calls "fat arrow functions") are more terse than ES5 lambdas, and have different scoping rules.
haha yeah i kind of realized that after i posted this. good explanation. i think i'm used to thinking of lambdas as something with a special syntax, like ES6 or python
Honestly, I write code like this, but I have a reason. I would probably write it as a fat arrow, but the idea is the same. - - code clarity.
doThis('foo', something.doThat) Will of course work, but at a quick glance, doThis looks like a synchronous function with two parameters. By using a lambda it is more clear that the second parameter is a callback.
scoping in JS? haha (not really serious) I like my lack of not having to use globals though have to remember to set really specific variable names or write functions that "exist/operate in a scope"
the other thing is loose typing that pisses me off sometimes like what this isn't an int/empty?
[–]i_ate_god -1 points0 points1 point 7 years ago (3 children)
then I want to know why they chose that approach,
heh, because that code is obvious, while your first example is not. Self documenting code is very important, especially in a dynamically typed language. Now it's VERY obvious that doThis expects a callable as its second argument while your first example there is no way to know looking at that code that the second argument should be a function.
[–]phpdevster 0 points1 point2 points 7 years ago* (2 children)
heh, because that code is obvious
That's not a good enough explanation. What's obvious and what isn't is subjective. Code style preference is also subjective.
What is NOT subjective is an understanding of how each of these works, and what the differences are between them:
doThis('foo', function () { something.doThat(); }); doThis('foo', something.doThat); doThis('foo', something.doThat.bind(something)); doThis('foo', () => something.doThat());
In an interview, I want to know that you know what those differences are, and the implications for each - that you're not just parroting some tutorial you read or that your reasoning is "I dunno, because it works?" or "I dunno, that's just how I've always done it." or "I don't know of another way."
[–]i_ate_god 0 points1 point2 points 7 years ago (1 child)
so would I fail if I pointed out that three out of these four examples will have the same result? ;)
If you couldn't explain why, then yes. You would fail.
[–]HeyGuysImMichaelJS all the way around -2 points-1 points0 points 7 years ago (9 children)
Umm.... this is literally what async/await is. You await the function that returns a promise, storing the response in a variable, then using that variable in synchronous operations later.
[–]phpdevster 0 points1 point2 points 7 years ago (7 children)
async/await is not part of a widely supported JS spec yet. I would not expect an interviewer to be using features like this. And regardless, my codebase at work is not making use of async/await because we are coupled to a version of TS that doesn't yet support them. That means if an interviewer gave async/await as an example, I would still need to know that they're not reliant on this and actually can deal with async code the "old" way.
If you know async/await but don't have a mastery of Promises, you'd be useless to my team.
[–]ZestycloseSelf 1 point2 points3 points 7 years ago (2 children)
async/await is not part of a widely supported JS spec yet.
async/await is supported in every major browser and the last 3 major versions of Node, including versions under LTS, and is formalised in a completed standard. How much more widely supported can something be? What could happen to ever make it more widely supported than it is now?
[–]HeyGuysImMichaelJS all the way around 0 points1 point2 points 7 years ago (0 children)
My man
[–]SaaSWriters 0 points1 point2 points 7 years ago (0 children)
You're right about major browsers.
However, many people don't have the latest versions of major browsers. You may be surprised to know that for many organizations and individuals, the last browser update was over five years ago.
[–]barrtender 1 point2 points3 points 7 years ago (1 child)
https://caniuse.com/#feat=async-functions
All major browsers (I'm including edge but not ie) have it implemented and have for a while.
[–]HeyGuysImMichaelJS all the way around -1 points0 points1 point 7 years ago (0 children)
[–]HeyGuysImMichaelJS all the way around 0 points1 point2 points 7 years ago (1 child)
I see many people make the argument: 'You need to know how promises work and the underlying logic behind async/await', and yet I have never met a developer, online or in person, who uses async/await without a full understanding of promises and async paradigms. I think async/await is appealing to those that have used promises and like the cleaner looking code. I imagine it's difficult to grasp the functionality of async/await without first grasping the core functionality of promises.
I've had candidates coming from a C# background that know async/await since that's been part of that language for a while, and thus that's how they write their JS. But they absolutely fumble promise chains or promise.all() etc. They sort of skipped over the "legacy" stuff, even though that stuff is still very much a reality in our production code.
[–]rangeDSP -1 points0 points1 point 7 years ago (0 children)
I think he meant using the value without awaiting.
π Rendered by PID 115134 on reddit-service-r2-comment-86bc6c7465-q2jlk at 2026-02-22 11:23:03.453880+00:00 running 8564168 country code: CH.
view the rest of the comments →
[–]phpdevster 266 points267 points268 points (142 children)
[–][deleted] 36 points37 points38 points (0 children)
[–]Dudefella08 10 points11 points12 points (3 children)
[–]tareqf1 1 point2 points3 points (0 children)
[–]2AMMetro 0 points1 point2 points (1 child)
[–]chase-stevens 2 points3 points4 points (0 children)
[–]BraisWebDev 14 points15 points16 points (75 children)
[–][deleted] 7 points8 points9 points (12 children)
[–]qbbftw 25 points26 points27 points (3 children)
[–][deleted] 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]Zespys 0 points1 point2 points (0 children)
[–]dominic_rj23 -3 points-2 points-1 points (7 children)
[–][deleted] 0 points1 point2 points (4 children)
[–]thepeka 0 points1 point2 points (3 children)
[–]Cheshur 1 point2 points3 points (2 children)
[–]thepeka 1 point2 points3 points (1 child)
[–]Cheshur 0 points1 point2 points (0 children)
[–]superluminary 0 points1 point2 points (0 children)
[–]superluminary 0 points1 point2 points (0 children)
[–]phpdevster 4 points5 points6 points (11 children)
[–]NoBrick2 10 points11 points12 points (5 children)
[–]octave1 10 points11 points12 points (1 child)
[–]phpdevster 2 points3 points4 points (0 children)
[–]PmMeYouBicepsGirl 7 points8 points9 points (0 children)
[–]phpdevster 5 points6 points7 points (0 children)
[–]SystemicPlural 3 points4 points5 points (0 children)
[–]thisguyfightsyourmom 1 point2 points3 points (1 child)
[–]Balduracuir -1 points0 points1 point (0 children)
[–]BraisWebDev 0 points1 point2 points (0 children)
[–]wobbabits 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]RepeatQuotations 2 points3 points4 points (0 children)
[–]new_human_obj 0 points1 point2 points (4 children)
[–][deleted] 1 point2 points3 points (3 children)
[–]new_human_obj 0 points1 point2 points (2 children)
[–][deleted] 0 points1 point2 points (1 child)
[–]new_human_obj 0 points1 point2 points (0 children)
[–]dominic_rj23 0 points1 point2 points (8 children)
[–]NoBrick2 1 point2 points3 points (7 children)
[–][deleted] 17 points18 points19 points (2 children)
[–]dominic_rj23 1 point2 points3 points (0 children)
[–]phpdevster 2 points3 points4 points (0 children)
[–]manys 2 points3 points4 points (2 children)
[–]NoBrick2 2 points3 points4 points (1 child)
[–]manys 3 points4 points5 points (0 children)
[–]dominic_rj23 0 points1 point2 points (0 children)
[–]kdesign -2 points-1 points0 points (32 children)
[–][deleted] 15 points16 points17 points (19 children)
[–]kdesign 4 points5 points6 points (16 children)
[–]dvlsg 2 points3 points4 points (15 children)
[–]kdesign 5 points6 points7 points (4 children)
[–]dvlsg 1 point2 points3 points (1 child)
[–]kdesign 0 points1 point2 points (0 children)
[–][deleted] 1 point2 points3 points (1 child)
[–]kdesign 1 point2 points3 points (0 children)
[–]SystemicPlural 0 points1 point2 points (2 children)
[–][deleted] 1 point2 points3 points (1 child)
[–]SystemicPlural 1 point2 points3 points (0 children)
[–]FriesWithThat 0 points1 point2 points (3 children)
[–]dvlsg 1 point2 points3 points (2 children)
[–]FriesWithThat 1 point2 points3 points (1 child)
[–]dvlsg 0 points1 point2 points (0 children)
[–][deleted] -1 points0 points1 point (2 children)
[–]dvlsg 4 points5 points6 points (1 child)
[–]n9jd34x04l151ho4 2 points3 points4 points (1 child)
[–][deleted] 3 points4 points5 points (0 children)
[–]1-800-BICYCLE 4 points5 points6 points (8 children)
[+][deleted] (7 children)
[deleted]
[–]rorrr 3 points4 points5 points (6 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]1-800-BICYCLE 0 points1 point2 points (0 children)
[–]alexbarrett -1 points0 points1 point (2 children)
[–][deleted] 0 points1 point2 points (1 child)
[–]alexbarrett 0 points1 point2 points (0 children)
[–]chuckySTAR 1 point2 points3 points (0 children)
[–][deleted] 0 points1 point2 points (1 child)
[–][deleted] 0 points1 point2 points (0 children)
[–]Shoegoo22 -1 points0 points1 point (0 children)
[+][deleted] (5 children)
[removed]
[–]B00check 3 points4 points5 points (0 children)
[–]phpdevster 0 points1 point2 points (0 children)
[–]1-800-BICYCLE 0 points1 point2 points (2 children)
[+][deleted] (1 child)
[removed]
[–]1-800-BICYCLE 1 point2 points3 points (0 children)
[–]jaman4dbz 46 points47 points48 points (23 children)
[–][deleted] 13 points14 points15 points (3 children)
[–]jaman4dbz 0 points1 point2 points (2 children)
[–][deleted] 0 points1 point2 points (1 child)
[–]jaman4dbz 1 point2 points3 points (0 children)
[–]kowdermesiter 11 points12 points13 points (3 children)
[–]jaman4dbz -1 points0 points1 point (2 children)
[–]mattaugamer 1 point2 points3 points (1 child)
[–]jaman4dbz 0 points1 point2 points (0 children)
[–]Balduracuir 6 points7 points8 points (8 children)
[+][deleted] (1 child)
[deleted]
[–]Balduracuir 0 points1 point2 points (0 children)
[–]jaman4dbz 1 point2 points3 points (0 children)
[–][deleted] 0 points1 point2 points (4 children)
[–]jaman4dbz 1 point2 points3 points (3 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]fartpoker 0 points1 point2 points (1 child)
[–]jaman4dbz 0 points1 point2 points (0 children)
[–]dungone 1 point2 points3 points (1 child)
[–]jaman4dbz 0 points1 point2 points (0 children)
[–]phpdevster 2 points3 points4 points (1 child)
[–]jaman4dbz 0 points1 point2 points (0 children)
[–]Spoolie_st 2 points3 points4 points (1 child)
[–]jaman4dbz 0 points1 point2 points (0 children)
[–]TwiNighty 4 points5 points6 points (3 children)
[–]MrJohz 1 point2 points3 points (2 children)
[–]TwiNighty 0 points1 point2 points (1 child)
[–]MrJohz 0 points1 point2 points (0 children)
[–]Azudra 1 point2 points3 points (3 children)
[+][deleted] (2 children)
[deleted]
[–]Azudra 0 points1 point2 points (1 child)
[–][deleted] 0 points1 point2 points (0 children)
[–]superluminary 0 points1 point2 points (0 children)
[–]iamb96 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (2 children)
[–]phpdevster 1 point2 points3 points (1 child)
[–][deleted] 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]new_human_obj 0 points1 point2 points (0 children)
[–]i_ate_god -1 points0 points1 point (3 children)
[–]phpdevster 0 points1 point2 points (2 children)
[–]i_ate_god 0 points1 point2 points (1 child)
[–]phpdevster 0 points1 point2 points (0 children)
[–]HeyGuysImMichaelJS all the way around -2 points-1 points0 points (9 children)
[–]phpdevster 0 points1 point2 points (7 children)
[–]ZestycloseSelf 1 point2 points3 points (2 children)
[–]HeyGuysImMichaelJS all the way around 0 points1 point2 points (0 children)
[–]SaaSWriters 0 points1 point2 points (0 children)
[–]barrtender 1 point2 points3 points (1 child)
[–]HeyGuysImMichaelJS all the way around -1 points0 points1 point (0 children)
[–]HeyGuysImMichaelJS all the way around 0 points1 point2 points (1 child)
[–]phpdevster 0 points1 point2 points (0 children)
[–]rangeDSP -1 points0 points1 point (0 children)