Hackernoon logoThe Weird Parts of JavaScript by@jcwii

The Weird Parts of JavaScript

J Chris Wingeier II Hacker Noon profile picture

@jcwiiJ Chris Wingeier II


Gotcha with a catchy title. Punchline: it's all weird. Case closed.

Nah just kidding but since you're here to stay a little while, hear me out. I'll run through some cross-language similarities but mostly point out key differences and by the end you may just agree that not all that is weird is bad. After all some of the weirdness is uniquely powerful and to harness it you'll just have to deal with the weird parts of JavaScript.

JavaScript powers the Internet. Sure HTML is the only in-browser language that's absolutely necessary to render web pages in a web browser, but go ahead and disable JavaScript in yours and see how far you can get along on your daily routine. In fact users can neither sign up nor login to hackernoon.com without it enabled. Even with all of JavaScript's power and necessity many people claim to dislike the language, with lower level programmers especially scornful of it. A lot of the disdain has to do with how this language behaves differently than others, and plenty of perplexing 

 screenshots float around the web to make the case.

Comparing Languages

For many, a first ever glance at a JavaScript file will quickly resemble other programming language files. Sometimes code is imported from other locations at the top. Then comes functions and variables. Curly brace syntax is commonplace for many developers and is even quickly intuitive to Python monolinguists.

For those well-versed in JavaScript (JS) it may come as a surprise that keywords promoted for use in modern JS (ES6+) are not unique. "async", "await" and "const" are reserved words in multiple other languages, and the keyword "let" was used all the way back in 1964 with the original version of BASIC. Even lesser used JS keywords like "abstract", "implements", "protected" and "volatile" have long been used elsewhere.

JavaScript is defined as being single-threaded with a synchronous execution stack; however, awaitable callbacks are made possible by modern browsers resembling multi-threaded asynchronous computing environments. That's pretty weird because an implementation seems to invalidate its definition. But definitions (nitpicking) aside, JS is dynamically typed, a concept shared with Python (PHP, Ruby and more), and differs from the many other popular programming languages which are statically typed.

Dynamic Typing

Unlike synchronicity, JS holds true to its dynamic typing definition. Values cannot be defined with mandated types such as integer and string unless using TypeScript, a superset of JavaScript. A great deal of JavaScript's weird parts stem from this inability to explicitly declare value types. If you've been writing JS for a while you've probably experienced this:

222 + 22 // returns 244
"222" + "22" // returns "22222"
"222" + 22 // returns "22222"

The addition operator concatenates numeric strings, as well as numeric strings with numbers. This behavior is consistent with the addition of non-numeric character strings:

"ab" + "cd" // returns "abcd"

One may assume then that the subtraction operator would deconcatenate numeric strings and numbers, thus returning "2" in the following case:

"222" - 22 // returns 200

Weird, right? Not exactly, it's pretty logical upon further investigation. If subtraction behaved like addition, you wouldn't be able to make sense of this:

"222" - 11 // returns 211

Sense is made of it though by returning 211. There's no way instead for deconcatenation to make sense of it, just like there's no way to make sense of this:

"ab" - "cd" // returns NaN

So if it makes sense, what's the big deal? Well that's what I wonder anyway, Wikipedia states that some of the above are "quirks that have been subject to criticism" (https://en.wikipedia.org/wiki/JavaScript#Weakly_typed). I'll counter with the opposite, the behavior above makes sense when considering bigger pictures. Enough of the sensibility though because there are certainly cases of JS behaving weirdly, especially involving data types:

[] + [] // returns ""
[] + false // returns "false"

Empty array and Boolean operations returning strings leaves me wondering how strings are implied. In the first case above I'd expect the return of a single array containing values from both arrays, and in the second case an error. Playing with the first case a little further:

[12] + [34// returns "1,23,4"

Again, I'd prefer an array containing those four numbers rather than the

 concatenation. For my wish to be granted I would instead need to do this:

[12].concat([34]) // returns [1, 2, 3, 4]

Yeah, that's weird. I'd like to see the above two examples return what the other returns but as they say: it is what it is. Back to adding an array and a Boolean, again I'd prefer to see an error and not a string containing false. In the same vein if I wanted an array containing a false Boolean I'd think the addition assignment operator (+=) would do the trick:

var array = []
array += false
array // returns "false"

But it doesn't. Again, another silly string. Oh well, I don't make the rules but here are just a couple more:

typeof NaN // returns "number"
NaN === NaN // returns false

null < 0 // returns false
null == 0 // returns false
null <= 0 // returns true

Look, there's a seemingly infinite amount of examples like these. Google "the weird parts of JavaScript", it's a little overplayed. My recommendation is to read what others have written before me, experiment with DevTools' console to build intuition, 

 values during development and send front-end errors to your server during production. Who's adding arrays and Booleans, anyway? Maybe use a little Python to clean up your data because as they also say: garbage in, garbage out.

Web Browsers

Statements upon JS's weird parts often gloss over or omit entirely the language's purpose. JavaScript along with HTML and CSS (known as client-side languages) work together directly on web browsers while other server-side languages can generate code in the aforementioned client-side languages. JavaScript was extended to work server-side with Node.js over a decade ago. JavaScript can create, modify and delete HTML elements, as well as set style similarly to CSS. Web browsers are obviously very complex and JavaScript is a common denominator because it has many capabilities, and even responsibilities that others do not.

Take a look at Mozilla's JavaScript documentation (https://developer.mozilla.org/en-US/docs/Web/JavaScript) and you may notice the usual programming language topics outlining statements, operators, functions, classes and errors, but you'll also find that an enormous amount of the language pertains specifically to the control of web browsers and Internet processes. Functions, objects and situations involved with JS differ fundamentally from C++, Java and other ubiquitous languages where runtime environments are often thought of in the context of operating systems like Windows and Linux. Instead considering that JavaScript mostly runs in browsers, developers must become accustomed to the workings of Chrome, Safari, Samsung Internet, Edge, Firefox and more.

Many languages send information from web servers to web pages. JavaScript is the language responsible for the opposite, sending information from web pages to web servers. It's doing a good job of making the web intimately interactive, and technology like WebSockets continually works to expand these more dynamic capabilities. Uniqueness (weirdness?) further stems from the fascinating functionality of Node.js (technically an abstraction upon JS). As of 12/23/2020, npm's all-the-package-names lists an astonishing total of 1,106,444 packages. Consider that at the same time Python, often touted for its extensibility, has 279,386 Python Package Index (PyPI) listings. It's undeniable that JavaScript and its tools are more functional than many like to admit, and I'll claim even more functional than many other languages labeled "functional" when it comes to everyday use. After all, scripting languages are made to get stuff done.

HTML has its weird parts, maybe you didn't know a variable can be defined in HTML with a 

 tag. There are a number of lesser-known tags like 
 (check out https://dev.to/christopherkade/unusual-html-tags-worth-knowing-3gbk for more). Adopting their use makes the task of creating search engine indexes (and snippets) easier. You're probably used to wrapping everything in 
tags on pages instead of using more descriptive 
 tags but admittedly, old habits do die hard. CSS has its weird parts too; vertical padding with regard to percentage is relative to the parent element's width, not height. Finally, a little Python:

>>> a = 256
>>> b = 256
>>> a is b
>>> a = 257
>>> b = 257
>>> a is b
>>> a = 257; b = 257
>>> a is b

I rest my case.


Are the dynamic typing problems any concern at all? Yes, of course at times they present problems for some people in some situations. But frankly some of the oddities floating around are so odd that people should deal with them simply by avoiding them. And by sticking to triple equals (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness) and maybe strict mode (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode) too. Write code that's conceptually more traditional, even if it is more verbose, and you will likely not only have more workable code but may also spend less time debugging. Verbosity can actually be brevity.

Otherwise to conclude it may be safe to assume that the language comes across a little weird because it does so many things that other languages don't. Considering we can quickly transport information comprised of ones and zeros and whatnot across space and time using various languages, it's all weird. So to harness the power of JavaScript, which is the power of the web, learn some about the weird parts but don't harp on them, in turn you'll be more powerful and less weirded out.


Join Hacker Noon

Create your free account to unlock your custom reading experience.