Why Evan does not like JavaScript as a first language

Power Overwhelming 2022-11-18

Some people have asked me why I anti-recommend JavaScript for beginners on my website FAQ. This post will try to give a few reasons why.

Some notes:

  • I’m referring to base JS. I like TypeScript a lot for example (it’s high on my tier list of programming languages for beginners). And I know about eslint, but you asked me about recommendations for beginners, and I think beginners shouldn’t have to worry about setting up an IDE with strict linting until after they can write a for loop by themselves without screwing up.
  • I have multi-file projects in mind. I don’t have a problem with using inline JavaScript for tiny 20-line snippets of code embedded in a webpage.
  • I’m an amateur programmer. Professional programming is a different ball game.

Weak typing

I’m clumsy. I make many more mistakes than the average programmer. The other day I finally installed a Django-HTML linter in OTIS-WEB and found out that the majority of my templates had mismatched HTML tags I never noticed for years.

If I write some nonsense code like

let x = 3;let y = x.value;

I would like the program to, you know, crash. It doesn’t. It sets y = undefined. And then 100 lines later I have to figure out why some other function didn’t do what it was supposed to, and trace back through the entire source.

It’s at a point where you can generate memes by just taking two different types of objects and adding or subtracting them and then laughing at the result.

Welcome to Node.js v19.1.0.Type ".help" for more information.> '7' + 3'73'> '7' - 34> 'hi' + ['i', 'am', 'a', 'potato']'hii,am,a,potato'> const x = 42;undefined> '1337' + x - x133700> '1337' - x + x1337> 'wtf' - 2022 + 'i?''NaNi?'

Like, at least in Python, you’ll get a TypeError or AttributeError or something when you run the code (but not at “compile time”, because scripting languages don’t have a “compile time”). Python’s my native language, and it still annoyed me so much that I use both mypy and pyright on all my Python code now to enforce what essentially became Python with static types, despite Python’s type system being janky af. You better believe I’m doing this with JavaScript too.

null, undefined, NaN

These keywords strike dread into my heart because I lack the professional training to keep the differences straight in my head.

Last I checked though:

Welcome to Node.js v19.1.0.Type ".help" for more information.> null === nulltrue> undefined === undefinedtrue> NaN === NaNfalse

Oh yeah, for those of you that don’t know, you always use === and not == these days because the latter operator is a total minefield:

> 0 == falsetrue> 0 == nullfalse> 0 == undefinedfalse> 0 == !!nulltrue> 0 == !!undefinedtrue> [] == 0true> const a = new Number(42);undefined> const b = new Number(42);undefined> a == bfalse> a == 42 && b == 42true

Well, == is supposed to be symmetric at least. Except apparently in Internet Explorer, where window == document is true but document == window is false, in some versions anyway.

Variable scope

It used to be that you could forget a var keyword and then suddenly your variable became a global variable. These days we have let and const and we just tell the beginners to always use one of these two and never use var (or worse no keyword at all) so I guess it’s not as bad as it used to be.

Though of course you can still find some contrived examples.

Welcome to Node.js v19.1.0.Type ".help" for more information.> (function() { const x = y = 1; })();undefined> xUncaught ReferenceError: x is not defined> y1

(For those of you that don’t know, the whole (function() {})() construction is an actual JavaScript idiom that’s used to prevent exactly this situation.)

And the this keyword still strikes fear into my heart. I can’t understand it for the life of me.

Modules and classes

The JavaScript base language used to have no module system. Now we have CommonJS and ES modules instead. Which I guess is fine, but it would have been nice to have these in the base language, you know? (I’m definitely not saying this because I spent an entire night fighting some node dependency chain where one component used CommonJS, and the other used ES, and they wouldn’t play along.)

These days I think people just use npm or something and be glad that with Python I have standard library that won’t collapse one day because left-pad disappeared suddenly.

Similarly, JavaScript uses a prototype-based object system that I never really understood either, because it looks like the classes I’m used to, but isn’t. If I was a professional programmer I’d probably take a few hours or days out of my life to figure out what the heck was going on. I’m not, and whatever beginner is reading my FAQ is definitely not.

Easter eggs

Actually these might not be a downside 🙂. I like Easter eggs. Maybe not in day-to-day code. But examples like this make for a good laugh, and they’re harmless because if you actually run into them in real life you’re doing something wrong anyway.

Welcome to Node.js v19.1.0.Type ".help" for more information.> null > 0false> null == 0false> null >= 0true> 100 <= 200 <= 300true> 300 >= 200 >= 100false> regex = /nani/g;/nani/g> regex.test('nani?');true> regex.test('nani?');false> [7, 12, 13].sort()[ 12, 13, 7 ]

See wtfjs.com for more.

Summary

JavaScript is the language that runs the web, so it’s kinda mandatory. If you want client-side code to run everywhere, it needs to be in a browser, so it has to be JavaScript.

But I still think people should learn how to program first, and then learn JavaScript, rather than the other way around. Or, at least start with one of the gazillion languages that transpiles to JavaScript so that you don’t have to fight language quirks and linters until after you’re feet are at least moderately wet.