IN THIS ARTICLE
Subscribe to Our Newsletter
Kyle Simpson is a freelance Open Web Evangelist based in Austin Texas. Kyle’s talk at Forward 2, entitled “What the JavaScript”, tries to “pull out the crazy” from JavaScript leading to cleaner, more elegant, more readable code and inspire people to contribute to the open source community.
Kyle’s book series, You Don’t Know JS, are available on GitHub, open source and free, as well as being published by O’Reilly.
Code WTFs
There are lots of people talking about WTF-style code in JavaScript, but many of these pale in comparison to the real WTFs of the language. I often find myself defending JavaScript, and explaining how the language is great.
WTFs are not just things that are funny (like typeof NaN
) or bugs, or ugly code idioms. We have the opportunity to improve those things, and we’ve done a lot of improvement in ES6. Cross-browser quirks are also out — I’m talking about things that are intentionally codified into the spec that produce inconsistent or unreasonable code.
“Many of the things I’m going to share today probably have some line of reasoning that led to them, other than just sheer stupidity.”
The MIN_VALUE Example
It’s pretty clear that Number’s MAX_VALUE
attribute is larger than zero. You might assume that MIN_VALUE
is the smallest number you can get; in fact, it’s the smallest *positive* number you can get. When paired with MAX_VALUE
, MIN_VALUE
leads to misunderstanding.
The .toFixed() Example
Kyle hates seeming inconsistency with the period interacting with numbers:
What’s odd to Kyle is that a little bit of a misplaced space can totally mess up the intent of the programmer. This happens especially in blog posts when people aren’t paying as much attention to white space.
“I’ve got a whole lot more crazy for you.”
Coercion
Coercion is often said to be evil; Kyle thinks coercion is awesome, and the third book in the YDKJS series is about how useful it is and how you should spend time using it. Let’s talk about some coercion implementations that are not WTFs.
This looks nuts; how can something be equal to the negation of itself? We have to understand that the equals and the negation don’t happen at the same time. When you negate an array, you’re taking it from a truthy-value to false, so you’re comparing an empty array to a false.
In the spec, when anything gets compared to an object, both things end up becoming numbers. What number should the empty array become? It becomes 0, and false also becomes 0, and the equality returns true.
If you pay attention to the coercion algorithm, it’s actually pretty reasoned like that, and not as magical as you’ve been led to believe. There are a lot of things that seem crazy and unexplainable, but are actually quite straightforward if you read the spec.
“Coercion […] is not as magical as you’ve been led to believe.”
JavaScript’s design philosophy may have been to do the best possible thing it can, rather than throwing errors everywhere. If you do something slightly invalid in Java it throws an error, but in JavaScript it makes a best guess as to what you were trying to do.
Coercion Craziness: Numbers
There is some coercion stuff that doesn’t make sense:
Why doesn’t the “.” evaluate to zero? Kyle thinks it may make sense to do this, but especially Number(undefined)
, which evaluates to NaN
, and Number(null),
which evaluates to 0
, should really match.
In the same vein,
Why does an object turning into a number result in NaN
, while an empty array turn into 0
? If you look in the spec, there are some reasons for this; empty arrays turn into an empty string, which evaluates to 0
.
“[T]here is some reasoning to it, but it results in inconsistency that drives obsessive-compulsive people like me nuts.”
Objects to Strings
If you try to coerce o1
, you get some garbage — if you try to coerce o2
, you get an error! Why do we have the inconsistency where sometimes we get errors and sometimes we don’t? (Here, because o2
was created as a null
prototyped object, it doesn’t have access to its toString
and valueof
.) Shouldn’t there be an exception to treat this more consistently?
New in ES6: Symbol
Without delving deep into everything about Symbol, Kyle wonders why Symbols can be explicitly coerced and not implicitly coerced:
There are long discussion lists about why TC39 thinks this is the right decision, but this inconsistency is going to trip people up.
“There’s lots of things we can avoid if we’re smart enough, but that doesn’t mean we should create footguns in the design of the language.”
Hating on Finally
Putting a finally
after a try
or try/catch
condition guarantees that the finally clause will run, even in the case of an error. Here’s some craziness:
There are definitely reasons to use a finally, but if you put an explicit return in the finally, then that return will override the original return!
ES6 Temporal Dead Zone
A variable can be in a special state where it has been declared, but not initialized. For example, the typeof
operator used to be considered pretty safe — you can use it with a variable that didn’t exist. However, if you use typeof
with the let
declaration, it’s not safe:
This is another inconsistency; if typeof
works one way with one type of variable, it should work with another type of variable.
Conclusion
JavaScript is a language that Kyle loves. Kyle will continue his open web evangelism and teach people. As Brendan Eich likes to say, always bet on JavaScript … and its WTFs.
Thanks to New Circle for providing video support. Kyle’s slides are available here.