WTFJS – a list of funny and tricky JavaScript examples
github.com
github.com
No, do not consider these examples as a "great" resource for interview questions. They are nothing more than tricks and hacks abusing the bad aspects of the language and anyone who includes them in an interview has failed in screening JavaScript developers, at least in my book.
A JS developer should understand that JavaScript has some flawed, unfixable core concepts and educate themselves on how to avoid them, not use them in actual production code or memorize every coercion scenario.
Some simple rules:
1. Always use referential equality checks (triple equal `===`). In idiomatic JS you can also use double equality only when explicitly checking against undefined or null (foo == null). It's the only use of abstract equality that I find acceptable.
2. Learn how the `this` execution context works. Kyle Simpson explains it very well in YDKJS (https://github.com/getify/You-Dont-Know-JS/blob/master/this%...). There are four simple rules that matter and are straightforward to grasp.
3. Familiarize yourself with how type coercion works in JS but avoid it. The spec is quite easy to follow in this matter and follows very specific, documented rules. e.g.:
https://www.ecma-international.org/ecma-262/8.0/index.html#s... https://www.ecma-international.org/ecma-262/8.0/index.html#s...
Use strictly as reference.
4. Stop using plain ES5, the language currently is ES2017. ES2015 and beyond provide modern constructs that make most of ES5's weirdness obsolete. For example, never use `var` anymore, `const` and `let` are superior initializers.
By following the above rules a JS developer should be fine in 99% of cases, in my experience. Yes, JavaScript will possibly implode on you on the rest 1%, but I'd be hard pressed to find a (similarly popular) language that doesn't. If one finds that to be unacceptable, enabling types via TypeScript or Flow should make their life even easier.
I've found this advice in guides and in codebases, but it seems unnecessary to me. The vast majority of equality checks are of the if (str == 'str') or if (n == 0) type. It's rare that you are actually comparing two objects of different types and when you are it's kind of nice to see === and know, otherwise it's just kinda ugly (kinda like const in languages, but we don't gotta hash that out here). There is a debate like this in the lisp community over eql and such. Similarly, isn't (foo == null) redundant? In most cases if (!foo) is what you are interested in and it's cleaner.
Is this incorrect? Would be cool to have it clarified. Have never actually run into a bug due to it, so not sure if the limitations of == are mitigated though coding style or what.
But in total agreement otherwise. Modern JS is really good, it's as productive as anything else, expressive, and once you know the quirks they are easy to avoid. Where JS has problems is inexperienced devs where they can code with var and for (var ...) monstrosities that date back to like 1996.
And I think the GP was talking about an existence check with the null comparison, like “did this function receive the argument false or no argument at all?”
Yes it is. The reason for the deep equality check is not so much that you want the check on type, but because this way you avoid the entire giant class of errors caused by type coercion, just like in PHP. Think things like:
function check_user_id(user_id) { return user_id == 1; }
check_user_id('1 error detected');
It's obvious when you see the exemples, and is usually a bug somewhere due to a missing check, but in language such as this it can often causes deep errors yet stay unseen for months.There is a reason why strict type hinting has become a most-wanted (and now beloved) feature of PHP, and of JS through language such as TypeScript: most of the time, you don't really care like you said if it's '1' or 1, but because it's supposed to be a number anyway it makes no sense to not force it to be one or error out.
In other words, it's better to trade "I don't want deep equality check most of the time" with "I don't want lax equality most of time".
I haven't found a use case where it would be necessary, and when it would seem it is, it's indicatory of code smell, e.g. badly formatted JSON responses.
Maybe a use case for abstract equality could be for comparing HTML data attributes (which all return strings by default using the web APIs). In this case it would be far better to abstract your HTML data attr wrapper to something like jQuery's .data method which will always return correct specific types rather than strings (e.g. data-bool="true" will return _true_ (bool) instead of "true" (string)). I believe many of JavaScript's old quirks are due to trying to interoperate with HTML better.
> In most cases if (!foo) is what you are interested in and it's cleaner.
In most cases yes, but there are cases where you simply want to check explicitly for undefined or null (e.g. does a variable or property exist or has a value, even if it's an empty string or 0). !foo means your variable isn't: an empty string, the number 0, the bool false, null or undefined.
It's also worth noting that `===` is not deep equality. It's merely referential equality (the equivalent of .is in other languages) for all non-primitive types.
e.g. [1,2,3] === [1,2,3] will always return false since the two arrays are different objects and point to different references. "123" === "123" will return true because they are both Strings (considered primitive types in JS).
Abstract equality will always fallback to strict equality when the types of the compared values are the same, but using strict equality everywhere avoids headaches that might come up during runtime.
Edit: I'm not sure why you're being downvoted, you're simply asking a question.
Javascript is weakly typed, so it can be hard to say what types are involved in the comparison. Using strict equality covers the case where the type isn't what you were expecting, circumventing unexpected behavior.
I also don't actually find it ugly.
3 > 2 >= 1 // true
What? No, JavaScript doesn't have chained comparison operators, as the author seems to know but not explain. Overall this list is pretty misleading and uninteresting IMHO.
it bothers me how the examples are often misleading or just misusing language features but people who don't know the language will gladly agree with them and have their "js sucks" belief reinforced
NaN === NaN // -> false
Are pretty f*&^%$ up, no matter how you look at themEdit: well, apparently there is a non f&^%$ up way to look at it: https://news.ycombinator.com/item?id=14891810
function isNaN(x) { return x !== x }
It’s a native browser function so it may not actually be done that way, but that’s one way you could do it.Also fun: (NaN < x) should be false for every x, and (NaN > x) should be false for every x. It's not a number, so it's not less than or greater than any number. But then by process of elimination, NaN == x for every x. Which is obviously nonsense. So equality and comparison is completely "broken" anyway when you start comparing NaN to things.
1/0 !== 1/0
This is not a very good explanation. NaN is used to represent a nonsensical value. By your explanation (1/0 === 1/0) should be true since they represent the same invalid opperation. The fact that NaN != NaN is not meant to mean anything, it is merely defined that way to prevent a class of bugs from occurring. Anyone not familiar with the definition is correct to be confused by it. I'd think if the spec was designed today, this special case (hack) wouldn't be there and we'd have exceptions in its place.
someone explained how it works here: https://news.ycombinator.com/item?id=14891850
The Array constructor's length property is defined to be 1, referring to the fact that if you call it with 1 number, you get an array of that length filled with undefineds. If you call it with something else or another number of arguments, you get an array filled with the arguments.
$python
Python 2.7.9 (default, Jun 29 2016, 13:08:31)
[GCC 4.9.2] on linux2
>>> True + True
2
>>>
okay... python3
Python 3.4.2 (default, Oct 8 2014, 10:45:20)
[GCC 4.9.1] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> True + True
2
>>>
I'm going to try this in Rust.https://play.integer32.com/?gist=4c95f461e58727607c4b1c2c569...
error[E0369]: binary operation `+` cannot be applied to type `bool`
--> src/main.rs:5:13
|
5 | let x = true + true;
| ^^^^^^^^^^^
|
= note: an implementation of `std::ops::Add` might be missing for `bool`Incidentally you can not provide one, because implementing a trait on a type currently requires that either the trait or the type be local to the current crate:
= note: the impl does not reference any types defined in this crate
= note: define and implement a trait or new type instead True, False = False, True
# fixed in Python3 $ python
>>> int(True)
1
>>> int(False)
0 >>> issubclass(bool, int)
True
>>> True == 1
True
>>> False == 0
True
[0] https://www.python.org/dev/peps/pep-0285/ >>> s = '12'
>>> int(s)
12
>>> s + s
'1212'As a comparison, how many WTF C++ examples could be constructed if people misused arrays, pointers, bitwise comparators, oeprator overloads, templates, etc... to create nonsensical operations?
These aren't misrepresentations (let alone 'strawmen', whatever that might mean in this context) and there is no 'tearing down' at all, just links to explanations.
(typeof (new (class { class () {} }))) // -> 'object'
It seems like we're declaring a class inside of class. Should be and error, however, we get an 'object' string.
Explanation:
Since ECMAScript 5 era, keywords are allowed as property names.
Can anyone explain why allowing keywords as property names seemed a good idea? To me it creates a lot of potential for confusion without providing enough benefits, but I'd like to be... enlightenedAnyway a lot of these examples can be explained if you know how type coercion works in JS and are aware what the `valueOf` method exists for.
Here's a nice write-up about this mechanism: http://2ality.com/2011/12/fake-operator-overloading.html
There's absolutely 0 benefit from an engineering standpoint in having type coercion memorized in JavaScript.
I'd personally immediately terminate every interview that posed such questions ({} + [] + '' or whatever).
I mean no offense, but I'd ask you to reconsider. People who ask trick/puzzle questions and hacks in interviews do not understand (or haven't thought deeply enough) how to properly screen JS developers which eventually goes through to the team itself. There are at least a dozen more interesting topics to question on if you want to assign extra points than useless stuff that should never be into production in the first place.
I would argue there is one:
tl;dr: Planning for the worst from the people who tend to generate code which is, in one word, bad but which they managed to push to production.
===
When you know you're going to work with people who are not familiar with this concept, but still managed to shoehorn some code that looks a lot like these examples.
Recent case: A local front-end server for development purposes and an SPA with a login form. The server checks for certain, hard-coded credentials and if they match lets the user through. Problem was, if you didn't get them right at the first try the proper credentials stopped working until you reloaded the page.
How did that happen? There's an extra field in the form that is initialized to an empty string, but if the form is reset(on login failure) it is set to null, while the server checks for: field == '', because somebody assumed this would be enough.
Null is falsy, but it's not equal to other falsy values. People who don't know that are usually left scratching their heads.
===
Anyway no offense taken and I'd be happy to hear some suggestions on how I could improve this process. Usually when I ask a "trick" question I give a warning beforehand indicating, that this is not something which is going to affect their score negatively. I found that normally people like this part and are often curious about the proper answer.
EDIT: One thing I would like to note is that I conduct interviews for the project which I'm currently in, so I'm going to suffer the consequences of any bad decisions on my part eventually.
I worked a couple times with a guy who was very smart but also quite arrogant. Each interview was an opportunity for him to show that he was "superior" to the candidate he was interviewing. One that sticks out in my mind was that this arrogant guy used to work at Amdahl and thus was knowledgeable about the IBM 370 instruction set. When the candidate said they had worked as a COBOL programmer on an IBM mainframe, arrogant guy jumped into action.
"Ah, so you know the 370? OK, then, when executing the numeric EDIT instruction and the format field is smaller than the number of digits required to hold the argument and there are an odd number of digits after the decimal point, what will the carry flag be set to upon exit?" Of course, the candidate didn't know the answer, and arrogant guy was quite dismissive of the candidate's abilities.
In my experience qualified people are first and foremost curious and usually bored enough with the usual stuff to start looking into things like these.
x = "053"
y = 50
z = "40"
x > y
// -> true
y > z
// -> true
z > x
// -> trueI actually had a bug because of this a while ago at work.
It's easy to use and widely available. Give me example of another computer language that is installed on every computer with internet access.
The base language isn't that bad, it's just that some bad initial decisions and backwards compatibility forced some really sharp paper cuts, most of you can avoid.
Does this means that One True JS Programmer can write flawless JS Code? No, but in practice you don't have to write flawless JS Code.