JavaScript Warts
no real array
no real array. js array is object. you have the situation of array-like object, and sparse array.
- cannot apply array methods on array-like things by normal dot syntax.
- in js, object basically is a map data structure.
- in js, array is object with string keys of integers, and a magic length key.
- in implementation, js “array” is implemented as array, but when there's a lot missing keys, it became a map data structure. no easy way to tell when.
Array Constructor problem
what it does depends on the arg type and number of args.
also, when given a single int arg, it does not actually generate a array, but a sparse array, so that when you use map to fill it, creates an error.
console.log(Array(3,4)); // [ 3, 4 ] console.log(Array(3)); // [ <3 empty items> ]
console.log(Array(3).map((x) => x + 1)); // [ <3 empty items> ]
some Constructor does not require new operator
some Constructor does not require new operator, some do, some have same behavior, some not.
no equality test on array, nor object
you cannot compare array by content.
console.log( [1,2,3] == [1,2,3] ) // false console.log( [1,2,3] === [1,2,3] ) // false
console.log( {p:1} == {p:1} ) // false
string is utf16 bytes
this means, all string methods, fail if the string contains emoji.
console.assert("🦋".length === 2);
no real type, they are just objects
function, regex, date, map, are all just object type.
by spec, they are all object type. this makes it a problem, because you need to know if a object is regex, date, map, etc.
however, typeof has an oddity that type of function return function. so, only for function, you can distinguish.
console.assert(typeof {} === "object"); console.assert(typeof (new Date()) === "object"); console.assert(typeof (new RegExp(".")) === "object"); console.assert(typeof ((x) => x) === "function");
many functions implicit convert type
// string plus array becomes array console.assert("abc" + [3, 4] === "abc3,4")
// isNaN convert arg to number first console.assert(isNaN("NaN"));
double equal implicit convert type
console.assert([] == ""); console.assert("0" == 0); console.assert("" == 0); console.assert(1 == true);
math function does not work with big int
// the ** operator supports bigint console.assert(3n ** 2n === 9n); // Math.pow() does not support bigint try { Math.pow(3n, 2n); } catch (xerr) { console.log(xerr); } // TypeError: Cannot convert a BigInt value to a number
many methods work on other type
odd and unintuitive and hard to use. no clear way to know which such method can be used on what other type.
- some methods works on other types. e.g. array's map method also work on array-like object.
- JS: String.prototype.repeat
// some function work on other type console.log(Reflect.apply(String.prototype.repeat, ["a", "b", " "], [4])); // a,b, a,b, a,b, a,b,
typeof null is object mistake
// null is object type console.assert(typeof (null) === "object");
no integer type
const x = 9007199254740992; console.assert(x === x + 1);
fixed by big int.
lots duplicate methods or syntax, one is improved of the other
Math.pow(x,y) vs x ** y
console.log(Array(3,4)); // [ 3, 4 ] console.log(Array(3)); // [ <3 empty items> ] console.log(Array.of(3,4)); // [ 3, 4 ]
Why JavaScript is the Suckest Language
JavaScript is truly the suckest language. There's no easy way to test object equality, forces you to change your code's algorithms, fundamentally.
and JavaScript syntax, is the worst possible. Code written by others is not readable.
why is js syntax unreadable? because
it has function expression, but it does not have the usual function programing languages's design to control it. JS is mostly imperative and prototype OOP, incompatible with function programing. Thus, you have passing function as argument and return function. This feature by itself, if used without fine control, creates incomprehensible code (e.g. y-combinator). (e.g. haskell has types, composition, currying, etc, to control complex function semantics.)
And JavaScript syntax is C/Java-like, provides no syntactic support for function programing. The passing function style becomes unreadable quickly. (e.g. lisp solves syntax problem by almost pure nested parenthesis, and haskell etc provides linear syntax (no parenthesis), and syntax that support semantic features such as currying, lambda, nesting, etc.)
Further, JavaScript design that was trying to emulate Java, created the following entities with exceptionally convoluted semantics.
- JS: this (binding)
- JS: prototype (property)
- JS: new (operator)
- JS: instanceof (operator)
- JS: constructor (property)
been thinking, to fix the js problem by removing some features, we'd gain a lot by,
- Ban the keyword
function. - Ban the keyword
this. - Ban the keyword
new. - Ban the use of property key
"prototype". - Ban the use of property key
"constructor". - Ban the keyword
delete. [see Delete operator] - Ban the keyword
var. - Ban
==.
JavaScript sucks
Spec Reading
- Reading JavaScript spec notes (2015)
- JavaScript Grammar is Not Context-Free (2016)
- JavaScript Syntax Complexity: Lookahead (2015)
- JavaScript sort, is fragile, and most complex, convoluted (2017)
- JavaScript Spec, Term “instance” is Not Defined (2017)
- JavaScript Spec Change on Date Time Zone Default (2022)
- The term INSTANCE in Object Oriented Programing
sucks
- JavaScript Warts
- JavaScript is Truly Bad Language (2025)
- JavaScript Sucks. Variations of Looping Thru Array (2025)
- Xah JavaScript Style Guide for FP
- JavaScript, what happens if you write all if-statement as if-expression (2015)