Do you really know JavaScript?
javascript-puzzlers.herokuapp.com
javascript-puzzlers.herokuapp.com
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.
The really nasty bugs come exactly from examples like these. This can save you hours at some point, I had to find some of them the hard way.
instanceOf is broken.
precision arithmetic on floats is broken
var hoisting and function scope is a misfeature
It's more useful to know those facts than to know the exact result of them in individual contexts well enough to answer a multiple choice question.
It's more useful, if you see these examples in real life, to just rewrite them from scratch to not use the broken parts of javascript.
Javascript has pitfalls and ugly parts. they can be avoided. this test gives you no great insight into them, or how to avoid them.
I don't think there is other language that comes close to javascript. Ok it's everywhere now, you make a lot of money with it, that's what we have now, but you and others defending it make my ears bleed.
Also sometimes you have to maintain code, so it's not a choice.
There are always explanations that are helpful. You have to know about the pitfalls to be able to avoid them.
The questions just make you study the examples and also it's more fun this way.
Sounds like one hell of a PR pitch. :)
I got 15/37, in no small part by guessing "what's the most bizarre and inconsistent thing that could happen here"? Apparently my imagination is less vivid than JS's.
And actually you could avoid using "typeof" by using polyfills/builtins for the new "is[Type]" range of functions in ecmascript5. or a similar one from a library.
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).
however, typeof NaN == "number" is a major wtf.
Especially PHP, which nobody is even forced to use. You could use any language on the server!
and Python. And Perl of course. Bash.
I bet you could make a similar quiz for Java too.
var array = ["a", "b"];
var otherArray = ["c", "d"];
otherArray.forEach(array.push, array);
console.log(array);
I expected array to become ["a", "b", "c", "d"], but it actually becomes ["a", "b", "c", 0, <Array>, "d", 1, <Array>]. This is because Array#push accepts 1 through n arguments, not just 1 argument.(I couldn't use Array#concat for reasons that don't show up in this simplified example.)
Your code sample is not surprising or obscure to someone who has skimmed documentation on "push" and "forEach"
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.
> What is the result of this expression? (or multiple ones)
[1 < 2 < 3, 3 < 2 < 1]
__[true, true]__ [true, false] error other
> Implicit conversions at work. both true and false are greater than any number.True and false are greater than any number? What? This is not only not correct, it is contradicted by the answer. The real explanation is that 1 < 2 is true, which converts to 1, and thus less than 3; meanwhile, 3 < 2 is false, which converts to 0, and thus less than 1. This is actually the same result you would get in C.
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. 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.
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.
There are some programmers who are walking encyclopaedias of language features. It is absolutely no guarantee that they are good coders. Some simply can't code at all, they know all the motions but cannot see how to thread them together past the simplest of programs. Others cannot distinguish between useful language features and terrible ones, using them indiscriminately and making a terrible incomprehensible mess. And of course some are simply the best programmers you will ever meet.
Javascript is a language full of terrible design decisions. Knowing them all doesn't make you a good coder, in fact simply being taught only the safe parts will often make a better coder than knowing a lot of the results of these parlour tricks.
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.
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?
In most of my limited experience JS has been harder to work with than almost anything I have encountered. My personal experience using JS client side apps has left me feeling sour. Every time I visit a webpage and immediately hit a JS loading screen I cringe. Gmail is about the only I dont completely dislike that I know is written in JS.
[typeof null, null instanceof Object]I think I would have a much better understanding of JavaScript if I knew how a good javascript engine works.
So would the people who write the good javascript engines.
I'm joking but only partially as they have to write an engine against both a standard and a convention plus support all the hacks going back years.
It's a mess but what I'm slowly and painfully learning is that if you avoid the shoals and hidden wrecks you can do some cool stuff with JS.
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...
Gary Bernhardt covered this humorously here: 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.
[ [3,2,1].reduce(Math.pow), [].reduce(Math.pow)] ]
has an extra "]".1 + - + + + - + 1
One plus (negative of ( negative one))? (and the successive pluses don't matter?)
/me sad face
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.
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.