
Do you really know JavaScript? - ndr
http://javascript-puzzlers.herokuapp.com/
======
TheZenPsycho
I really wouldn't draw any larger conclusions about Javascript from these
examples or from the results of this test.

These are edge cases.

 _every language has them_

No sane programmer would put anything like these examples in a normal program,
and knowing these edge cases doesn't really help you solve problems or get
things done. Because you just won't encounter them in real life.

~~~
lmkg
I disagree, several of these issues can come in up innocent programs written
by less-seasoned practitioners. For example, [] not ==ing [] seems like it
would be an incredibly common noob mistake. Some of the auto-conversion rules
make certain classes of true bugs difficult to find. And I could see someone
from a more 'traditional' OOP background getting bitten by "string" != new
String("string") != String("string).

I will give you that many of these test cases are simply looking for trouble,
especially the examples explicitly monkeying around with, especially anything
involving direct manipulation of prototypes. I am also personally not bothered
by most numeric wonkyness because that's floats in general, not JavaScript in
particular (though I wish it had true Ints).

~~~
leeoniya
when you realize that "[]" is the same as "new Array()", it's not at all
confusing.

however, typeof NaN == "number" is a major wtf.

------
Zarel
This question is wrong:

    
    
        What is the result of this expression? (or multiple ones)
        
        "1 2 3".replace(/d/g, parseInt)
    

It says the correct answer is "1 NaN 3" but the real correct answer is "1 2
3". I assume it's a typo of:

    
    
        "1 2 3".replace(/\d/g, parseInt)
    

In addition, for several questions, such as this:

    
    
        var x = [].reverse; x();
    

Their 'official' answer is only true outside of strict mode. So to add to
TheZenPsycho's comments, not only are these edge cases, many are edge cases
that are known and that strict mode tries to solve.

I also object to []==[] being false as evidence that == is the spawn of Satan.
== may be weird, but this is a case where === does the same thing. You just
have to understand that [] and {} (and regex literals) construct new objects,
and objects are compared by reference, not by value.

~~~
magicalist
For the

    
    
      function f() {}
      var parent = Object.getPrototypeOf(f);
      typeof eval(parent.name)
    

one, this is also wrong. I can't find anywhere in the spec that a name is
required for Function.prototype[1], and 15.3.4.2 actually says that
Function.prototype.toString() can return "An implementation-dependent
representation of the function". Spidermonkey assigns it no name, so

    
    
      typeof eval(parent.name)
    

just returns 'undefined', it doesn't throw an error. There's certainly no
requirement that it be invocable by name, and, indeed, if v8 had left a
function named 'Empty' in the global scope, that would have been bad.

[1] [http://es5.github.io/#x15.3.4](http://es5.github.io/#x15.3.4)

~~~
magicalist
Also, using 'class' as an IdentifierName is incorrectly explained in the
answer for

    
    
      var a = {class: "Animal", name: 'Fido'};
      a.class
    

as this will correctly return "Animal" in most browsers. It may be true that
it's buggy in IE, but that's a bug, not part of the language. 'class' is a
reserved word, but only as an Identifier, not an IdentifierName.

That might seem like a confusing splitting of hairs, but that's just due to
the fact this is from a spec, not an explanation. In practice it basically
means that you can't declare a variable with a reserved word name, but
something like a property name (like a.class, or used when initializing a
variable via an object literal) is fine using a reserved word.

In fact, the difference between an Identifier and an IdentifierName has
allowed more than a few of the changes coming in ECMAScript 6 to be backwards
compatible.

Even when not excusing browser bugs, there's a lot of sloppiness in this quiz.

~~~
Zarel
`a.class` is explicitly legal in ES5, which is the spec that explicitly allows
trailing commas in the `[,,,].join(", ")` question, so it's at least a bit
confused about which version of JavaScript it's quizzing.

------
steven777400
This is a good way to distinguish between someone who knows JavaScript the
language from someone who can apply JavaScript to perform DOM manipulation and
data requests.

Not that there's anything inherently wrong with the latter.

I fall firmly in that latter camp; I do all my algorithmic work and heavy
lifting in C# and just use JS to get data onto the client and display it. But
it's easy for someone like to me to start believing "I know JavaScript" when
in reality, it's more accurate to say "I can use JavaScript in the browser for
common client/server cases". I'm currently working through "Effective
JavaScript" to help improve on this.

~~~
wil421
Agreed, I use Java for my heavy lifting. Use JS to display the data, provide
some client side validation on forms, switch some classes around or manipulate
something in the DOM using JQuery or the like.

I cant create a full fledged client side JS app but I dont really need to if I
have a larger language helping on the server side.

~~~
lennel
I create fully fledged JS apps on a big scale, the difference from this test
to reality is startling. The difference is I enforce the use of the closure
compiler in our team so 99% of these issues are caught by the compiler. end of
story. this test is bullshit.

~~~
Pacabel
What exactly do you mean by "fully fledged JS apps on a big scale"?

When it comes to more traditional languages like C, C++ and Java, "fully
fledged" and "big scale" are descriptors usually reserved for multi-million
line systems consistently worked on by 50+ full-time developers at a time.

I'm very suspicious of such terminology being applied to JavaScript
applications. We generally see a much, much smaller scale when it comes to
those. The "high end" cases are usually topping out at 100,000 to 200,000
lines of code at most, and perhaps 10 or 20 developers. They're a far cry from
the C, C++, Java and C# examples.

Is any of this code you've worked on publicly available?

~~~
lennel
i mean teams of 20-25 people, working with millions of lines of code over all
the modules, that has to be regressed the whole time. Big for the tech stack
it is. This is not counting our bucketloads of java and scala code as well.

------
davexunit
Holy fuckaroni JavaScript is a mess of a language. I did terrible on this
test.

~~~
ycmike
Agreed. I don't want to ever show my score.

~~~
SonicSoul
Agreed. I already made arrangements to have my things shipped to Alaska where
i will live out the rest of my days .. this "programming" thing didn't pan
out.

~~~
ycmike
That is rich.

------
eonwe
Not that I am so sure about he usefulness of this, but there is at least a
double of this question:

    
    
      [typeof null, null instanceof Object]

~~~
anon_d
I got it right the second time!

~~~
danabramov
I got it wrong both times. Ouch.

~~~
icholy
I did too.

------
flebron
I may be alone in this camp, but I'd actually recommend people read the ES5
spec if they want to be confident in their JS. It's one of the most readable
and understandable specifications I've read, and (compared to behemoths like
C++) is fairly short. There's even an internally-hyperlinked version at
[http://es5.github.io](http://es5.github.io) .

~~~
icholy
If you want a readable langauge spec check out
[http://golang.org/ref/spec](http://golang.org/ref/spec)

------
clavalle
I wish there was a 'JavaScript Under the Microscope' like 'Ruby Under the
Microscope' by Pat Shaughnessy.

I think I would have a much better understanding of JavaScript if I knew how a
good javascript engine works.

~~~
gcommer
The author of this quiz could have made this a great learning opportunity by
linking to the appropriate sections in ECMA-262[0].

For example, question 15 makes a lot more sense when you read "ToBoolean" (Sec
9.2) which shows that all objects (including arrays) are always considered
truthy values, however when compared with ==, "The Abstract Equality
Comparison Algorithm" (11.9.3) is used, which gives this behavior:

    
    
      >> [0] == [0]
      false
      >> a = [0]; a == a
      true
    

because a shallow comparison is used.

[0] [http://www.ecma-international.org/publications/files/ECMA-
ST...](http://www.ecma-international.org/publications/files/ECMA-
ST/Ecma-262.pdf)

~~~
anaphor
So it's like Scheme's "eq?", except less useful?

------
sek
It feels more like an interactive version of wtfjs.

------
grannyg00se
I got two out of two and then stopped. This is another "look how many weird
results we can get out of javascript" exercise.

Gary Bernhardt covered this humorously here:
[https://www.destroyallsoftware.com/talks/wat](https://www.destroyallsoftware.com/talks/wat)

And Crockford covers some issues more formally in his talks.

The takeaway is that if you do something that can possibly be interpreted in a
strange way, javascript is mostly likely going to interpret it in a way that
you didn't expect. You could say it sucks because of that and/or you can look
at the ecmascript standard and try to reason about it. But either way, it's
best not to do anything even slightly ambiguous. Stick to the good parts.

------
mattparlane
This line:

    
    
      [ [3,2,1].reduce(Math.pow), [].reduce(Math.pow)] ]
    

has an extra "]".

------
trevorhartman
Yes, but I don't know the answers to these questions because I know to avoid
code like this.

~~~
nfm
Sure, some of these examples are pretty academic (eg ` Array.isArray(
Array.prototype )`). But can you truthfully say you never get bitten by basic
JS arithmetic fails, given how many ways it's possible to accidentally coerce
numbers to strings?

~~~
trevorhartman
Years ago, perhaps. Can't remember a specific instance.

------
rubiquity
Can we please stop pretending JavaScript is some esoteric language?

~~~
Pacabel
I don't think that anyone really considers it "esoteric". There's not really
any secret to it. Once one accepts that it's just a very poorly designed
language, it makes perfect sense why it's so heavily broken in so many
critical ways.

------
jimmaswell
I'd never heard of reduce, filter, and some others here, although I've written
an emulator and a 3D game in JS. I guess sticking with a subset of JS you know
to be safe is good. Using good libraries like jQuery too.

------
scrabble
So what's a good score? I got just under 50% and was considered a "Working
Practitioner." Not as high as I'd have hoped, but I'm in a hurry to get home.

------
c2u
"1 2 3".replace(/d/g, parseInt), I guess it should be "1 2 3".replace(/+d/g,
parseInt)

------
cheapsteak
What's the logic of this one:

1 + - + + + - + 1

One plus (negative of ( negative one))? (and the successive pluses don't
matter?)

------
general_failure
Wow, i thought i was really good at javascript. I tried 7 questions at random
and got 6 of them wrong.

/me sad face

~~~
increment_i
Same here. JS has some seriously bizarre gotchas.

------
johnbm
"it goes into an infinite loop, 2^53 is the highest possible number in
javascript, and 2^53+1 gives 2^53, so i can never become larger than that."

This is wrong. 2^53 is the highest integer value you can represent exactly
with a 64-bit float without truncation, but much larger numbers are available,
spaced more than 1 unit apart.

So 2^53 == 2^53 + 1 != 2^53 + 2 != 2^53 + 3 == 2^53 + 4 == 2^53 + 5 != 2^53 +
6.

~~~
magicalist
> _2^53 is the highest integer value you can represent exactly with a 64-bit
> float without truncation, but much larger numbers are available, spaced more
> than 1 unit apart._

Yeah, that one bothered me as well, though to be fair, it is a hard condition
to phrase. You also gave a definition that isn't quite right, as 2^53 + 2 is
an integer value that can be represented exactly with a 64-bit float without
truncation :) Perhaps you meant "exactly" in a somewhat more nuanced way.

You'd have to phrase it as something like every positive integer less than or
equal to 2^53 can be exactly represented with a double precision float. Of
course, there are more positive integers above 2^53 that can be exactly
represented by a double than there are below, they're just spread farther and
farther apart, as you said.

