website/content/blog/js.md

3.5 KiB

+++ title = "Why I hate JavaScript" date = 2023-01-20 insert_anchor_links = "left" draft = true [taxonomies] tags = [] +++

Why do people use JavaScript? Because it's a great language or because it's the only one ready-to-use in any web browser?

Note that several of these arguments also apply to PHP, another de facto application-specific (web server) language, that I think is mostly used because of technical debt.

This article is about JavaScript for web browsers, not NodeJS or TypeScript.

TL; DR

JavaScript combines most of the problems of both high and low level languages.

Lack of features

JavaScript is obviously not made for being used in webpages.

  • jQuery is needed for manipulating DOM or network in a convenient way.
  • no native HTML escaping function
  • no native basic templating system (need String.replaceAll("{{foo}}", foo))
  • no easy-to-use bytes array (like Bytes in Python or Vec<u8> in Rust), but many different bytes arrays with weird interfaces
  • no native cryptographic tools if you aren't using HTTPS and satisfying other strange "security" requirements (you often end up inefficiently implementing SHA2 or AES in JS, while the browser natively uses OpenSSL)
  • no native date/time string formatting
  • When defining an anonymous function (such as a callback) you can't reliably move variables to it.

Having a decent standard library would reduce the use of weird hacks hence the number of bugs, and the use of libraries hence the traffic and webpage size and loading time.

What the fuck

JavaScript doesn't respect anything.

  • You never know whether you're copying or borrowing (a table or an object), and how deeply.
    • Python suffers the same problem.
  • Time is expressed in milliseconds, while the convention is seconds everywhere else.
  • if("2" == true)
    	console.log("I am not executed.");
    if("2")
    	console.log("I am executed!");
    
    • Hence ==, === and if have three distinct strictness levels.
  • && is not commutative: (true && "2") === "2" && ("2" && true) === true is true
    • It is even inconsistent: "0" == false && "1" == true is true... but so is "0" && "1".
  • Operators are inconsistent: we have both "1"+1 === "11" and "1"*2 === 2
  • var n = "1";
    n += 1;
    // n is now "11"
    n ++;
    // n should be "111"?
    // but n is now 12
    
  • (-1)%2 == -1 while most of the time the convention is to give the least positive congruent.
  • Naming is incoherent. XMLHttpRequest is an example mixing all-caps and first-letter-cap conventions for initialisms. It should have been either XmlHttpRequest or XMLHTTPRequest.
  • Is an array really an array, or an object with some of the array's properties? Lua has the same problem.
    var foo = [];
    foo["bar"] = 42;
    console.log(foo["bar"]); // foo["bar"] exists.
    console.log(foo.length); // 0
    
  • document.getElementsByClassName does not return an array: its return type supports indexing but not for/in loops.

Conclusion

Let's deprecate JavaScript and replace it with better languages compiled into WASM.

However, plain HTML/CSS should always be prefered, for performance, compatibility and accessibility. Form inputs crafted with tons of CSS and JS are often unresponsive, not accessible to screen readers, incompatible with native features, inefficient. It is even worse for pages rendered in a canvas. Please use the wonderful possibilities offered by HTML5 and CSS3, and follow the accessibility recommendations by the W3C and Mozilla.