JavaScript Nonsense (Part 2 of probably many)

Bit-wise Operators

Hey you remember how in part 1 of me complaining about JavaScript I was quite annoyed with the language’s disregard for different types of number? Hey guess what I’m still quite annoyed. Because reasons, JS includes operators for doing some of my favorite nonsense, bit-twiddling-hackery. I love me some good bit-twiddlin’, but I ended up getting caught in a weird way by this implementation of my favorite operators.

let num = 1 << 4;

Cool this is all fine. num is a number and its 16 now no problems here. Everything in JavaScript is a 64 bit floating point value, so bitwise operators don’t even really make a whole lot of sense. To counter this, all bitwise operations in JS are done after converting the values to 32 bit signed integers. After the work is done, it gets converted back. Some people probably are upset about the data loss here but eh we’re in web land who cares. (Probably people writing networking code, who are honestly probably the only ones trying to bitshift in JavaScript)

void(0)

This isn’t something you’d reasonably expect to encounter in code written by a human, but for some reason the language supports it anyway. In most languages void means “nothing”. You just put it as your return type, your function doesn’t return any value. In C, if your function accepts nothing you should make your function accept void. In JavaScript those things are still true, but void is also a function. You can call it at runtime. It accepts exactly one argument, and returns undefined. Any other number of arguments, unlike any other function in JavaScript, will cause a failure to compile. This is actually in almost any large JS library because void(0) is less characters than undefined and therefore you have to download slightly fewer bytes. This is one of the operations often completed by minifying tools.

“Optional” Semicolons

Look I know programmers are lazy and that’s part of the reason we’re programmers. I get it. Apparently JavaScript gets it too, since we don’t even have to bother typing those pesky semicolons like those ‘oppressive’ languages with all their boring ‘rules’ that limit my ‘creativity’ do. JavaScript lets you be a free spirit unbound from the tyranny of the semicolon.

However.

function foo()
{
  return
  {
    a: 'bar',
    b: 'baz',
    c: 'bam'
  };
}

This is perfectly fine code (according to JavaScript). It will run just fine and when you call foo it will return… nothing. This function returns nothing. It return type, if JS had such an opressive and freedom limiting concept, would be that function that accepts a single argument from earlier. JavaScript is detecting that return on its own is a valid statement, so its helping you out and adding a nice little semicolon in there to help you out. Thanks JavaScript, what I wanted was to return then not reach the code that creates an anonymous object. Perfect. If you are used to programming with a style guide that enforces braces on their own lines (like I was) things like this will bite you.

I guess this is the price of freedom?

JavaScript Nonsense (Part 1 of probably many)

Honestly the main reason I started this blog was to have a new outlet for the things that my college game project team called “You Wanna See Some… Stuff”. Without working next to those nerds every day I need a new outlet to either vent frustration or share excitement about the absolutely bizarre ‘features’ I encounter in programming languages and sometimes libraries.

To that end, I present to you…

JavaScript’s Array and the Indexing Operator

Ok so, I don’t want to dunk on JavaScript too much, even though it is absolutely hot garbage. It does somehow drive most of the internet (including this blog), so I’ll be gentle. It’s just… sometimes… this language. This particular ‘feature’ cost me almost a whole day of work to deal with.

Ok so.

const array = [0, 1, 2];

for (const i in array) 
    console.log('Content is ' + array[i]);

Pretty good so far? This all works perfectly and performs exactly as you’d expect. Modern JavaScript does have a cool way of iterating through arrays that tidies it up a little. (For the uninitiated, in defiance of what makes sense for…in loops in JS actually move through all the valid indices on an object. More on that later)

for (const value of array) 
    console.log('Content is ' +  value);

This works the exact same, as you’d expect. I just thought it was worth mentioning. The reason for this will become clear shortly.

So for you poor sweet uncorrupted souls people that haven’t worked in JavaScript: everything is a table, and the generally accepted lie is that all numbers are just numbers (none of that float/integer segregation here). This is the point at which I begin to become annoyed.

So everything is a table. You can access the things in the table just like a table in any other language.

const thing = {};
thing["key"] = "value";

Cool that makes sense you can just use it the same as a table in any other language thats neat. And just like in any other language, its the same operator as an array. No big deal. Except this is JavaScript and we don’t care what types are. So what happens if we do this.

thing[0.23] = 1.0;

Answer: not much different. Now there is another key on the object so if you ask for 0.23, you get 1. Neat.

Sidenote: Because objects in JavaScript are just tables, we can now ask for thing.key and get "value" out. That’s kinda weird but ok just a different syntax that you can use if your key is a string that is legal as a variable name.

So going back to the array from earlier. What happens if we subscript a string onto that array? Its an array right? So indexing with a string should fail? Since everything is at a numeric index? Oh sweet summer child you’re thinking like we’re dealing with a sane language. Everything here is a table. Everything.

So lets try it. We’ll also keep using the neat little for…of syntax because its tidy.

const array = [0, 1, 2];

array["dumb string here"] = "a string";

for (const value of array) 
    console.log(value);

That looks weird but given what I know so far I’d expect to see 0, 1, 2, “a string”, right?. Heres the output:

0
1
2

No string? It almost makes sense. The array is indeed an array. But its also a table. Internally there is a dynamically resizeable array of values, and then also a table. For…of only iterates through the array part, and ignores the table. If we got back to the for…in loop, the output is as we’d expect:

0
1
2
a string

Ok but this raises a question. JavaScript says there is only one type of number, where other languages differentiate between integers and floating point values. So if using indexes 0, 1, 2, etc put things in the array space, what about the other numbers that the standard claims are the same type?

const array = [0, 1, 2];

array[0.5] = 0.5;
array[1.5] = 1.5; 

for (const value of array) 
    console.log('of: ' + value);

 for (const i in array) 
    console.log('in: ' + array[i]); 

OUTPUT:

of: 0
of: 1
of: 2

in: 0
in: 1
in: 2
in: 0.5
in: 1.5

So clearly all numbers aren’t being added to the array part of the object, since they didn’t show up when we iterated through using of. That means that although these numbers are pretending to be the same type, that is a lie. JavaScript standards can say all numbers must only be 64 bit floating point values as much as it wants, but when two values that are supposed to be the same type are fed into the same operator, I would expect consistent behavior, and I don’t think this counts.

Ok I get it you don’t think this is a huge deal, but hear me out.

Lets construct a hypothetical situation where I’m building an API for others to use to store constructed images built in a frontend on my backend. These images have a concept of layering so that people can separate their background/foreground objects or whatever. So you’d expect layer 1 to be in front of layer 0 cool, cool. Easy we just put the content in a 2-dimensional jagged array with the first array being indexed by the layer number and the second being the content for that layer. Problem is we’re in JavaScript land and numbers are just like, numbers man why do we have to segregate the integers from the floating point. The language has no problem with someone asking for their content to be on layer 0.5. This is a public-facing API so I can’t just tell my front end people to please not.

So what? Just iterate using for…in why is this a big deal? But look at what for…in output up there. That’s not in order. If someone really did put this picture of a tree on layer 0.5 they probably expect it to be between layers 0 and 1, but according to that iteration its going to be drawn on top of all the integer layers. That’s not right. Now we have to sort this nonsense and slow everything down. Hope you didn’t need a stable sort for that because there is no requirement for a stable sort in the JavaScript standard. Anyway that was a purely hypothetical scenario that hypothetically wasted a lot of my time to sort out a problem that in typed languages wouldn’t exist.