> If you are a professional developer, you can consider these examples as a great resource for interview questions and quizzes for newcomers in your company
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.
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.:
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.
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.
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.
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:
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".
The answer (in my opinion at least) is that yes `==` should be avoided, if for nothing else then simply because it's totally unnecessary and only adds a mental overhead.
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.
I think the issue is that you do want non-strict equality 90% of the time, but correctly identifying the 10% where you need strict equality is difficult and impossible to automate. So you end up weighing cognitive overhead and subtle type bugs vs an extra equals sign, which seems like an easy choice to me.
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?”
> It's rare that you are actually comparing two objects of different types
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.
We can fix this with Greater than or equal operator (>=):
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
To those curious what it does, Object.create(Array) creates an object with the Array constructor function (not the Array prototype) as its prototype. The Array constructor function, like all functions, has a length property indicating the number of arguments it takes. That property is accessed through the created object's prototype chain.
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.
NaN is meant to represent a non-sensical mathematical operation (like divide by 0). One non-sensical mathematical operation is not the same as some other non-sensical mathematical operation (1/0 !== Infinity/Infinity)
>NaN is meant to represent a non-sensical mathematical operation
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.
As long as you can define what's going on rigorously, it's just mathematics :) The equality operator means just what I choose it to mean- neither more nor less, as Humpty Dumpty would say.
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.
NaN is not a name for one thing. You could think of not a number as not any particular thing. There is no comparison with itself, because there is no it.
Great discussion indeed. I was thinking along the same lines, the comparison may be meaningless, but “false” is not a good answer either, even though a Boolean is either true or false by definition and NotABool would be even more crazy. What a rabbit hole.
$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
>>>
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`
> = 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
Such blatant misuse of the language in these examples. Not sure what to think. It seems like the author has a good understanding of JS, but then goes out of the way to purposefully misrepresent things to construct strawmen simply to then tear them down. If someone comes across this without being familiar with JS, they could very easily be misled.
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?
There is plenty of verbiage at the top explaining the motivation (some of it even under a big heading 'Motivation').
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.
You might trip on one of these misfeatures when a variable doesn't contain what you think it does. Or when you make a typo. In those cases, you're generally grateful for a strongly-typed language or a strict compiler.
(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... enlightened
Because they found out they had little reason not to, and it can be convenient e.g. in Python when messing around with metaprogramming you have to use `cls` or `kls` or `klass` rather than the obvious `class` as a local variable name, just because keywords can't be used in other context. It's even more annoying in JS as e.g. a property named `class` is very common in DOM contexts.
> From now on I'm going to include at least one of these in each interview I'll be conducting - for extra points of course.
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.
> There's absolutely 0 benefit from an engineering standpoint in having type coercion memorized in JavaScript.
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.
Go ahead and use your tricky questions, but (a) only if you knew the answer before reading it on that website and (b) you desire to screen out qualified people who avoid the arcane corners of the language.
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.
Thing is, these questions here are mostly not "tricky" by any means. Most of them are just examples of how type coercion works in JS. Sure this not something one encounters very often, but for this reason I warn people that the following question is not graded - I'm just curious if they know. I have found that people like these kind of questions and are often curious what the proper answer was. Makes for a nice break and sometimes sparks some interesting conversations.
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.
It's interesting to see that a lot of people make fun of JS, publish articles on how weird it could be, receive a ton of likes, but still it's the most popular programming language at the moment. It's like Stockholm Syndrome we developed with time!
> It's like Stockholm Syndrome we developed with time!
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.
I agree that most of "very strange things" about JS can be avoided. 90% of these "look, js is weird" articles are quite useless as they make use of very artificial scenarios.
These are merely extreme cases. Javascript is full of less mind-boggling inconveniences. It's not like they only kept the really bad features for laughs and fixed the rest.
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.