Hacker News new | comments | show | ask | jobs | submit login
Ask HN: “Expert Level” JavaScript questions?
57 points by aphextron 32 days ago | hide | past | web | favorite | 50 comments
I'm just curious what kind of in depth, JavaScript specific questions you've seen before or asked candidates. I'm working up the courage to apply for senior roles, but I'm terrified of looking stupid not knowing about XYZ technical thing that 99% of devs don't know.



A good interviewer will start at a high level and drill down into what you're experienced with, rather than pick an obscure topic and assume you've done your homework.

For example, they might ask for a hard problem you've recently solved in your last company.

If you say something related to code splitting, you can expect he'll drill down more specifically into webpack, dependency cycles, etc.

If you say something related to frameworks, you'll get questions asking you to back up the choices you've made. Was it mainly developer productivity or performance you optimized? If you say performance, how did you measure? What metrics are you logging?

...

You should prepare by just reviewing hard problems you've done and brushing up on aspects of it you might've forgotten or remind yourself what was difficult about it.

This applies to the coding portion of your interview as well. If you write "===", you should be able to answer what that's for. If you use ".bind(this)", you should know why you had to bind it. For this portion, you can prepare by looking at code you've written and trying to pick out those parts which you never bothered to figure out but always "just did" (e.g. for many people, the === is just something they do because they see it everywhere).


By this metric, extremely few interviewers are good, and candidates should assume an interviewer won’t be good and instead do the esoterica homework & trivia memorization, as there won’t be economic returns to one’s interview effort otherwise.

If I had known this as a high school student, I never would have studied math and computer science. Easily one of the most anti-inclusivity and self-defeating aspects of tech.


As an interviewer, you don't even exactly have to be an expert. Maybe you have no clue what .bind does. But you will learn a ton about the candidate by listening to them teach you about it.


My favorite interviews (both as the interviewer and interviewee) are the ones where I end up learning a lot from the other person. I love when a candidate mentions some technology I'm not familiar with, and then I get to make them teach me all about it.


"here's a high-level description of a fictional product. Let's have a discussion about where you start, what kind of technical and and design discussion you make and what goes through your head as you would theoretically tackle this project".

Not exactly what you want, but that's still what I'd ask.

That will tell me more about the candidate's abilities than syntax questions or other silly things like that. INCLUDING how good they are at syntax and silly things (the way they speak will show it).

What I like about these kind of open-ended problems, is that it accounts for variety of backgrounds and skillsets. People can surprise you with solutions and ideas you'd never have thought about.

It does require 2 things: 1) make it absolutely clear that this isn't a question with a predefined answer. 2) you have to be open minded about how the candidate answers.

Most frontend devs will go through their frameworks of choice, project structures, backend tooling preferences, how they sketch a UI, how they work with designers, etc. I had one once walk me through a complete system architecture analysis. We gave them an offer to lead our devops team ;)


Interview questions for senior roles won't (or at least shouldn't) be about language specifics but instead about managing a team, distributing technical work, managing timelines etc. Needless to say, depending on the company, ymmv.


Imo few questions should be. I've seen some "senior" devs that was just above typical junior, still not good enough to be called a "good middle". Filtering them out as soon as possible saves some time for both parties.


Not necessary. There are lots of senior/experienced/veteran engineers and roles without managerial obligations (at least formally).


There are some weird corners of JavaScript that I went years without knowing. Did you know object literals support getter and setter methods[1]?

As other commenters will point out, such quirks are as easy to look up as they are irrelevant to actual software development.

[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guid... "Defining getters and setters"


God, I used to go nuts with defineProperty and such back in the day. Kind of a bummer that it's even easier to do with ES6, cause that code was usually bad news.


Reimplement things from scratch. I’d recommend implementing Promises from scratch as well as several Async [0] functions like auto or series. Both are questions I’ve asked of senior level JS/Node engineers. This isn’t exhaustive but it’s good practice for sure. Good luck!

[0] https://github.com/caolan/async


> I’d recommend implementing Promises from scratch

That must be downright hilarious, depending on how the question is asked. Promises are an absurdly complicated construct considering how little they actually do. If you don't give the candidate the expected spec, 95% of candidates won't get even close. If you do, working through the answer will take long enough that the candidate (and honestly, the interviewer) might get bored.

If you simplify the problem space a lot and ask for a minimal "promise-like"-ish construct, then It can be an interesting coding exercise I guess.


Like any good interview question it leaves a lot of room for the candidate to take the lead, ask questions and define the scope of the problem. These are all useful skills to assess for a senior position.

Of course an hour long interview is not enough time to implement the full Promise spec but it should be enough time to gauge the level of a candidate.


Explain why ['1','1','1'].map(parseInt) returns [1, NaN, 1] but ['1','1','1'].map(n => parseInt(n)) returns [1, 1, 1].


Thanks for the chuckle.

To save everyone from having to look this up on Stack Overflow:

.map passes two arguments to the function it calls - the value and the index. The parseInt function takes up to two arguments, a string and a radix.

So there’s nothing broken here about .map, you just aren’t expecting the second optional argument for parseInt.

So the actual equivalents are: ['1','1','1'].map(parseInt)

And

['1','1','1'].map((n, index) => parseInt(n, index))


What the hell, who on earth thought that behaviour would be a good idea?


No one ever thought it would be a good idea, Contravariant. :/ It's just an unfortunate interaction between two APIs. Map's callback gets three args, and parseInt takes two (and ignores the third). After a while, you get used to wrapping callbacks to slough off the spare variables as shown.

In this case, the index of the element (1, 2, 3) is getting passed as the radix with which to parse the element (1, 1, 1).


Probably the same person who thought

    [1, 2, 3, 4].reduce((x, y) => Math.min(x, y))
should be 1 but

    [1, 2, 3, 4].reduce(Math.min)
should be NaN, for similar reasons. Unfortunately it's a recurring theme in JS that a lot of useful functions have optional extra parameters and a lot of useful higher order functions pass extra context to their callbacks, causing many traps for the unwary if you try to use these tools in a style that works fine in most functional programming languages.


.map(fn) calls its callback with three arguments, the value, the index, and the full array. Then parseInt takes two arguments, the string and the base (radix).

"1" of base 0 is 1

"1" of base 1 is NaN

"1" of base 2 is 1

The gotcha here is if you map(fn), you're going to get all three arguments sent to the fn, where map(v => fn(v)) explicitly only sends the first one.


I see. I'll remember this example for when someone asks why you need types.


this is more than just types though. Typescript, even in strict mode, will still allow this! You need strict function arity/signature checking of some kind, which a dynamically typed language could have, and a statically typed language could lack.


If a language can't detect the difference between a function a => f(a) and a function (a,b) => f(a,b) then I would consider it very weakly typed indeed. Dynamic vs static isn't really the issue, Python will also complain if you call a function with the wrong number of arguments.

Then again I suppose that you could recreate JavaScripts behaviour even in the fairly strongly typed C# if you wanted to, by defining two overloaded versions of Map as follows:

    IEnumerable<B> Map<A,B>(this IEnumerable<B> list, Func<A,B> f)
    IEnumerable<B> Map<A,B>(this IEnumerable<B> list, Func<A,int,B> f)
in that case C# would also choose the latter Map when you call it on a function with an optional int argument, similar to what JavaScript would do. However C# will never ignore an optional argument when you're passing around functions, so it's more consistent in that sense. And overloading a function in this way is not the best idea in the first place, it's just that JavaScript kind of encourages it.


Nobody thought about it or did that on purpose to confuse you with this particular example. If you would do js enough you still could be surprised at first but then you'll see it's pretty valid behavior. map will pass value and key to the method given. so it will call parseInt('1', 0) parseInt('1', 1) parseInt('1', 2)


Hah! That's amusing. It took me a moment to realize what might be happening, and then another moment to confirm it. Another funny example is:

  ['1', '2', '3'].map(parseInt)
This would be a bummer to be put on-the-spot to answer. It was fun while not being in an interview though.


Try this ['1','1','1'].map(Number).

That's just about language specifics, not a question for seniors in my opinion.


Senior roles require that you can break down large problems into digestible chunks. "gotcha" questions don't tell an interviewer how good you are architecting, or how well you understand the language. "gotchas" are usually easily Google-able too.

I've asked a lot of code structure questions. JS really easily turns into spaghetti code if a dev isn't careful. I like to test candidates on whether they make code understandable with clean closures, modules, files, etc. I'll also ask about which libraries they used, why they used them, and what they liked/disliked about the library. Also, "because that's what the code base was in, and there was no reason to change it" is a legitimate 'why'.

For language specific things: - How closures, scopes, and prototypal inheritance work is important. This is often tested with nested callbacks. - Web API design - HTTP methods (Not as important if a candidate's background is in RCP, GraphQL, or something that doesn't use HTTP methods RESTfully)


I completely agree with your core point. I really hate gotcha questions too (and have come close to walk out of interviews over them quite a few times).

On the other hand, ""gotchas" are usually easily Google-able too." isn't that simple. You don't know what you don't know. We're in a world now when even some extremely senior devs don't know the tools they use. A lot of it can be blamed on the whole "if you know one language you can learn any other in an afternoon!" tenet. Having so few people these days with vertical/deep knowledge of the tools they use gets really annoying when trying to deal with major production issues and no one in the room can debug them in a timely manner.

Almost makes me think that some form of "tech guru" role should start being a thing, and THOSE people could be interviewed with the stream of obscure gotchas...because sometimes you need a tech guru.


Know the details around bind, 'this', dot operator, 'new', call/apply, 'in', variable hoisting, the actual data types JS provides out of the box (Longs aren't one of them) and some assortment of new features/proposed features like classes, and you'll be ahead of lots of seniors. Personally I'd appreciate a good showing in knowledge of the standard library, where its gaps/gotchas are, levels of browser support... (e.g. even IE11 supports sets -- we can use actual built-in set data structures! -- just not the full API. But it has the minimum.)

I agree with others though that you probably won't get the trivia treatment, I wouldn't give one and I don't see them being done by coworkers... But it doesn't hurt to be prepared. So long as you don't present yourself as a "Master" I would think the knives would be less likely to come out. Things like this github has https://github.com/denysdovhan/wtfjs are on the mean spectrum to use against some so-called master, the meanest might probably be demanding they do something with representations like in http://patriciopalladino.com/blog/2012/08/09/non-alphanumeri...


Some guy from "the book store" once asked me to implement memoization[1] in JavaScript during a live screen share.

A year later another guy from "same book store" asked me to center text in a div during a live screen share.

So, YMMV and its all parlour tricks anyway.

  just.apply(you, ['who', 'knows', 'anyway]);
[1] https://jsfiddle.net/ronilan/c27n8f2j/


Senior level JavaScript I would imagine it to be entirely about frameworks and ES6 shims a.k.a. things you don't actually need. I recommend using as many buzz words as possible.


> ES6 shims a.k.a. things you don't actually need

Though it sounds a bit jaded— can confirm. I've been asked to re-implement `bind` before.

I gave it a shot but ultimately shrugged and explained that I'd rarely ever extend a native object and would rather use a community-supported polyfill. Nevermind that in my current field we haven't had to support ES3-capable browsers for ages.

I'd certainly be better off knowing, but rarely would I need to know on the spot. There is more beneficial knowledge to have up front.


I'd say these days "knowing" something is far less important than being able to "learn" something.

If I'm ever in a position where I'm responsible for technical interviews I'm pretty sure I'll give them open internet questions. Then ask them to talk me through their thought process. Even though questions could probably be answered by anyone with decent skills, the best will certainly stand out in how they talk you through their thought process.


There are the run-of-the mill senior level generic questions about high level knowledge and procedure. I'll ignore those since you asked specifically about expert level general JavaScript knowledge (not specific to node or front end):

You might see a dumb question that is just a bunch of spaghetti nonsense you'll have to unravel. Explain what this ridiculous codeblock does.

Definitely expect to see closure-based problems. You can almost bet your money on seeing an anonymous function in a loop printing an unexpected value of i:

(copy these code blocks into your browser console and test them out)

    for(var i = 0; i < 10; i++) {
      setTimeout(function() { console.log(i); }, 1);
    }
Event loop: Explain it in words or pictures. Explain why

    setTimeout(func, 0);
works.

variable scoping with var, let and const. Variable and function hoisting. Expect brain teasers exploiting the differences in const / let and var:

    const x = [1, 2, 3];
    for (var i = 0; i < x.length; i++) {
      setTimeout(function() { console.log(i, x[i]); }, 1);
    }
Scoping and binding. Function.prototype.bind(), Function.prototype.apply(), Function.prototype.call(). Maybe explain why you have to bind ES6 class methods used in callbacks.


can someone explain why setTimeout(func, 0); works?


1) setTimeout is a Browser/Node API, not a Javascript method

2) Functions that are being returned from the Browser API are pushed to a special waiting area (called the "Callback queue"), not to the immediate Call Stack

3) Functions are only taken from the Callback queue when both the Call Stack and the other higher priority queues (like the "Job" Queue) are empty.

When setTimeout is invoked, the Javascript engine sends func and 0 as arguments to the API, then moves on. The engine doesn't get blocked by setTimeout, nor does it wait to see the end result. Javascript's job is done here, and so it just moves on to the rest of the code.

When the API receives setTimeout's arguments, it executes the Timer(?) method, passing to it an argument of 0 seconds. This resolves immediately.

However, the API isn't allowed to send functions straight back into the Call Stack. Functions are forced into an intervening waiting area called the Callback Queue. (In the case of promises, there's also a higher priority queue that functions can be sent to instead: the "Job" or "Micro-task" Queue).

Javascript's event loop will only pull functions from the Callback Queue when 1) the main thread of execution has finished all of its synchronous code, 2) the Call Stack is empty, and 3) no higher priority queues have functions left to be pulled either.

Therefore, in the case of "setTimeout(func, 0)", func can be forced to wait a very long time, indeed. If the intervening synchronous code takes 10,000 ms to run, the func from setTimeout(func, 0) will, at a minimum, run at the 10,000 ms point.

However, back in the days of "callback hell", this was often the reason why you'd do a "setTimeout(func, 0)" or two in the first place: to manipulate the order in which certain functions were run by the thread of execution.

Since, literally, what it does it knock a function out of the normal order of events and places it into a lower priority queue.


I assume GP meant "how it works". Why it works is because the spec says so and the native code behind it makes it. Why does func() work, or 1+1?

How it works is func is scheduled to execute asynchronously on the next tick of the event loop at the soonest, so if func() printed "wat" and you have console.log('huh') directly after that statement, you'd see "huh" then "wat"


setTimeout enqueues "func" onto the event queue of the current (typically, only) thread. Thus, "func" can only run at the earliest at the beginning of the next loop iteration of the event queue consumer.


I'm not sure if this can help you prepare for an interview quickly but most advanced JavaScript things I've learned is by taking a deep dive into existing frameworks like AngularJS, jQuery, etc source code.

You see a lot of things happening which may not make sense like "The Great Mystery of the Tilde(~)"[1], etc which are not only fun to figure out but you also see them being used practically too.

[1] https://www.joezimjs.com/javascript/great-mystery-of-the-til...


Good lord OP don't rule yourself out before someone else does. Just apply. You need to apply to go on at least 4-5 interviews (and bomb some of them) before you get a hang of it anyway.


Bad advanced JD questions will involve quirks of the language that experienced JS developers will have learned to avoid, like details of how type coercion and == work.

Good advanced JS questions (in my opinion) will involve things that are useful but also challenging, like details about promises, prototypical inheritance (that one is debatable, since some JS experts avoid that), the browser event loop, etc.


I was once asked about what I would remove from JS. The following discussion touched JS linters and coding style.

But as other have already pointed out, quiz-type questions that are trivially searchable and irrelevant for practical programming tell about a culture of the company. Use that as hint if you want to work for them.


IMHO serior roles isn't really about javascript question but more about architecture, high-risk operations, leading/managing teams, testing, software trade-offs, etc.


Why creating an element and afterwards setting it to invisible, will never end with a 'blinking' element.


Not a JS Engineer - is it because the DOM isn't updated until the script yields?


To make element visible, you need to attach it to the document :)


Nice one


I pay you for a day to pair program with us in our codebase.


trickiest/deepest questions ive ever gotten are:

variable hoisting

how to extend a class/prototype

es6 features

typescript/flow

tdd

tooling/webpack


Nothing about context? Sad. You can find many tricky questions and all of them would be about context.


write your own version of function.bind()




Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: