5-part JS quiz (link)

Came across the blog post so, you think you know JavaScript? by Dmitry Baranovskiy. It's a pretty nice little 5-part quiz on JavaScript quirks. I admit I did have one wrong answer (the fourth one), what's your score?

Rather than just linking to it I'll explain all the examples and why exactly you get the result you do … but not just yet πŸ™‚ I'll first let my dear readers dive in and take the quiz. Explanations will follow in comments (unless you all beat me to it, of course).

Advertisements

34 thoughts on “5-part JS quiz (link)

  1. Hrmm.. if I'm running it correctly, it appears I got the 4th one right… and I can't for the life of me work out what alternative answer you could've given…Other than that I failed 1, 3 and 5 πŸ˜› … and can't figure out why I got 5 wrong :((3 I understand, and 1 I just guessed wildly anyway)

  2. Originally posted by anonymous:

    @lucideer: if like me, you thought a was a "object" and not a "pointer" to arguments[2]

    Aha.. ok. I actually thought it was the other way around (arguments object elements are pointers) but hey – thanks for the explanation.

  3. Mariusz Nowak writes:Question is, do really good JavaScript developer have to know that (I mean immediately). It's extremely rare to see code that resembles situations like in those examples and if it is, it's poor code by poor JS developer.Isn't it just art for art's sake ? πŸ™‚

  4. @MariuszI would say what is demonstrated in at least three of those tests is potentially useful to know for any javascript developer – it's not just art for art's sake, it's testing the extent of your understanding of how javascript operates.

  5. @lucideerI did about the same as you. I couldn't really figure out how another answer could be confused on #4 either until explained above. #2 and 3 were the ones that got me, but those are probably just as easy for others. Cool post, thanks for sharing Hallvord!

  6. Got the 2nd one wrong because I second-guessed myself.Got the 5th one wrong, but I should no better on that. I'll blame that one on a memory lapse.:)Got the rest right. But, getting the 4th one right was probably due to your warning and due to just seeing the topic at hand on some list or bug report the other day.

  7. I still seem to be the only one here who doesn't really "get" the 5th one – obviously the null object is not being passed to the function for some reason – is this simply an oddity of the call() method or am I missing something else?

  8. Originally posted by lucideer:

    is this simply an oddity of the call() method or am I missing something else?

    See 15.3.4.3, 15.3.4.4: on page 248 of the 5th edition spec for some talk about this. There may be other sections too.

  9. Aha, so it's an ES3 oddity, and I would've gotten the 5th one right using an ES5 compliant interpreter. Good to know – that's one change I wasn't aware of.

  10. Looks like a.call(undefined) does the same thing at #5…#4 seems a bit evil, since you don't really see pointers in javascript. My first thought was that it was a trick question and that a is passed by value (so the call to arguments[2] shouldn't have an effect on a), so this one really surprised me.

  11. I got #1 and #3 wrong. I offer my preliminary analysis of the cases.#1 was a gotcha. I think it would be against best practice to even try such a thing though. My fleeting analysis says variable declarations are completely ignored in conditional statements.#3 kind-of makes sense if you think of it as purely "variable declaration" instead of "variable declaration and instantiation". It works the same way in other languages. Some of those languages don't allow the use of uninstantiated variables, though.In short: the expressions var a; and var a = undefined; are not equivalent.#2 is about the difference between function declarations and function expressions. Function declarations can't appear on the right side of an equal sign. IE (used to?) to have a bug where this works differently.#4 is about the arguments object, which works like an array that provides shortcuts to named function parameters (and all unnamed arguments). Everyone who's used the arguments object to get at things passed to the function knows about this.#5 is about the well-known methods to create references to the window object (where the global context is used as a default object to pass).

  12. Jeff Walden writes:lucideer, the semantics of #5 are not different in ES5 and ES3. ES5 strict mode does differ from ES3, however, but without a strict mode declaration around (and there is none here), there shouldn't be such a difference. See ES5 10.4.3 steps 1-2.

  13. Jeff Walden writes:There's a link to actually test against (which you probably will have to copy/paste manually) — do note that I had to alter the snippets a little to eliminate inter-snippet name collisions. Assuming I didn't mess that part up, I got all the answers right. Yay me, or something. :-)#1 is slightly twisty to think through but trivially answerable if you understand JS scoping. #2 I knew because I know that IE is or has been buggy on that point in a particular way, showing the correct answer by elimination. #3 I was partly confident about because I've been looking at ES5's semantics for var statements recently. #4 is a weird bit I've osmosed over time, I think due to the considerable pain arguments has caused for my fellow JS hackers working on making its uses, common and esoteric, fast and safe (respectively πŸ˜‰ ). #5 I'm not sure I even consider to be arcane knowledge (isn't this bit of semantics common knowledge among library authors desiring particular this-binding?), but maybe I've just been studying JS semantics and specs for a long time.

  14. I had 4 and 5 wrong. The scoping questions didn't faze me at all, I second-guessed myself out of 4 (thought that arguments was passed by reference, then thought that must be too obvious and didn't go with my instinct). 5 I was never going to get – I've never really had much to do with .call().

  15. Now, lemme see if I get this right…#1 The variable declaration, like all variable declarations, is secretly moved to the start of the current scope. As a result, it behaves as if the first line of that script was "var a;" and only the assignment "a = 1;" happens inside the conditional. The same then happens with function declarations (in browsers that support ECMAScript 3, not Gecko's "JavaScript 1.5" which only moves them to the start of the nearest conditional). #3 is just another demonstration of that effect.#2 relates to how a function name does *not* become a global variable during an assignment. It can, however, be used inside the function code as a reference to the function (and yes _Grey_, IE has some bugs there).#3 then checks that variable instantiation happens before function instantiation, as mentioned under point #1, and that the resulting variable then becomes the function reference *if* and only *if* the variable has been instantiated without already assigning it a value. (I may have missed some of the rules here, but that seems to be correct.)#4 demonstrates how the arguments object uses the index to lookup the relevant parameter name, then acts as a pointer to the local variable with that name (it's done internally with a setter function, I think, according to section 10.6). It's quite unusual for JavaScript to have pointers for primitive variable references, so I'm not surprised that like Hallvord, I forgot that part and got the answer wrong.#5 .call() is run as a standard method. However, .call itself then runs the function as if it was a method of the first argument passed to the .call() method. From section 10.4.3; "if thisArg is null or undefined, set the ThisBinding to the global object". As a result, "this" ends up as a pointer to the global object, which in browsers is "window". It's sortof like the script engine does this:Function.prototype.call = function (oThis) {if( oThis === null || oThis === window.undefined ) {oThis = window;}oThis.__temp__ = this;oThis.__temp__(restOfArgumentsGoHere);delete oThis.__temp__;};

  16. Originally posted by fearphage:

    I missed #1 and #4. It would be a totally different set of answers in IE.

    Yeah, but then the test was for Javascript – you can get away with anything when you call yours Jscript! :p

  17. I got both #2 and #5 wrong. Humbled again.#2 I got wrong because I incorrectly assumed that function a would be created in the global scope, instead of not at all.#5 I got wrong because I expected 'this' to reflect the function itself, rather than a global scoped object (window, apparently).As far as I remember, I've always had problems with 'this', unless used inside an object function.

  18. Commenting here with first impressions prior to reading the other commentsI failed 1. Does the ("a" in window) part secretly declare it in some internal scope?Passed 2. This one seemed the easiest to me, although before I failed 1 I would've thought 1 and 2 were the easiest.Failed 3. Very interesting, I did not know this was possible. I would've expected it to just say something like [function object].Passed 4. I have never seen this arguments stuff before, but I figured it had to be meaningful because Hallvord said he failed. Turns out I interpreted that one right. I think I would've failed it otherwise.Failed 5. First I thought it would refer to the scoped object (like window), but the whole .call(null) part means nothing to me (is that bad?) so I assumed it was meant to modify it to refer to the function itself or something along those lines. Something I wouldn't expect, at any rate. Turns out the result is the same as just calling a(); which in retrospect seems logical. Why would you use call without anything in it though?Anyway, no need to reply to anything I said specifically if it was already addressed in the preceding comments, like I said, I managed to avoid reading any except the first.[edit]Reading other comments now.Originally posted by johnnysaucepn:

    Originally posted by fearphage:I missed #1 and #4. It would be a totally different set of answers in IE.Yeah, but then the test was for Javascript – you can get away with anything when you call yours Jscript! :p

    I originally learned "javascript" in the form of Jscript. I may still have some leftover bugs in my head.Originally posted by _Grey_:

    #1 was a gotcha. I think it would be against best practice to even try such a thing though. My fleeting analysis says variable declarations are completely ignored in conditional statements.

    While I tend to declare all variables I use in a function at the top of that function (a habit I've got from Java, but I do think it makes things easier too), that's certainly not true. There's definitely something special about this particular issue. Tarquin's explanation does seem to make a lot of sense.[/edit]

  19. Jeff Walden writes:lucideer, the requirements of "use strict" are partially implemented in Firefox nightlies. Try loading any of these in a recent build (see nightly.mozilla.org):javascript:"use%20strict";function%20a(b,b){}javascript:"use%20strict";function%20a(){var%20arguments;}javascript:"use%20strict";with(1){}and open the JavaScript console to see a few requirements that are implemented. The remainder are being implemented now and hopefully should be finished in the next few weeks.

  20. Anonymous writes:"#3 then checks that variable instantiation happens before function instantiation, as mentioned under point #1, and that the resulting variable then becomes the function reference *if* and only *if* the variable has been instantiated without already assigning it a value."This isn't quite an accurate description. |var foo| does nothing but add a binding for |foo| in the relevant scope *if it doesn't already exist*. In the case here the function definition added the binding already, so the var does nothing. (Now, if it had an assignment associated with it that assignment would run and would overwrite the binding with a different value. Logically, |var x = y| is better thought of as |var x; x = y;| where the first part does nothing except create the property if it doesn't exist and the second part unconditionally makes an assignment to that property.)Also worth pointing out is that function statements are parsed and global bindings/properties for them are created before non-function statements execute, so this:javascript:var%20x=function%20x(){return%2042;};function%20x(){return%2017;};alert(x());will alert 42, not 17, even though the assignment to x precedes the function statement going in source order.

  21. Originally posted by anonymous:

    the requirements of "use strict" are partially implemented in Firefox nightlies… … The remainder are being implemented now and hopefully should be finished in the next few weeks.

    Great. Are these changes tracked by any particular BTS entries?Originally posted by anonymous:

    wish this blog software saved commenter name.

    It does if you register πŸ˜‰ (and also supports BBCode for quotes and pre-formatted code btw.)

  22. Michael points out the correct bug link. (This is still Jeff, just logged into a very ancient Opera account I barely remember having set up, back in the mists of time when dinosaurs roamed the earth and everything was more hardcore. The connection between being logged in and having commenting details auto-saved is not well-suggested in commenting UI here…)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s