« Truthy and Falsey | Main | In the Hopper »
Monday
Oct062014

JavaScript Types and Conversions

I figured, when I started on JavaScript, that there would be a point where the familiar turned into the unfamiliar, and I've definitely reached that point. About half of the book I've been using to learn JS has covered the familiar stuff. How to assign values to variables, how to make functions, loops, conditional checks, etc. While I hesitate to call it easy, it's the stuff that seems to be in common with all C-based languages. The syntax might be a little different, but the fundamental concepts are the same. But now I'm getting into new stuff, and I can't tell if this is just new ground for me in general, or if this stuff is unique to JS. I'm suspecting it's a little of both.

I recently finished a chapter that delved into JavaScript's...um...interesting approach to types. I had initially embraced JS partly because it's loosely typed. I can probably attribute that to starting with PHP. I found C# frustrating at times because there was no automatic type conversion, and I would frequently run into errors when trying to run code because I was trying to mix the wrong type. At the time I would admit that there are benefits to the C# approach, but secretly I was like "This is dumb, I miss PHP". Now that I've lifted up the rock, and seen all the creepy crawlies, I'm starting to think maybe a strongly typed system isn't so bad.

I had a thought when I was learning PHP. It was basically that it seemed like several people started working on different parts of the language, and sort of met up in the middle, but they didn't quite match up. So much of the language made good logical sense, except for a few odd patches. Naming is inconsistent, and sometimes built-in functions that seem very similar operate differently. JS seems more consistent, but there is one kind of rough patch, and that's all this types and conversion stuff.

The basic stuff isn't so bad, you just have to keep it in mind. Like with comparisons done using ==, JS will automatically try to convert strings into numbers to compare them. So "5" == 5 is true. The strict equality operator === has no time for such shenanigans. Numbers can only match numbers, strings can only match strings, etc. This is the same in PHP, so this stuff wasn't any big surprise. Booleans will convert to 1 for true, 0 for false, same deal. 1 == true may not look right, but it'll evaluate to true. The math operators are fun too. At least with comparisons you can always use === to suppress that fun conversion, but there's no way to make the math operators strict that I know of. So "8" - 7 will evaluate to 1. That's not so bad, except if you're trying to add. Then it flips and treats everything like a string. So "5" + 5 will evaluate to "55". It'll even work with empty strings. 5 + "" + 5 is 55.

Ok, that stuff is just fun messing around. Why I really wanted to write this was to talk about NaN. I don't think there's a NaN equivalent in PHP. NaN stands for Not a Number, and is used to represent numbers that are unrepresentable. This is all the stuff that would give you the error message on your calculator. 0/0, trying to find the square root of negative numbers, stuff like that (I totally knew that off the top of my head and didn't just peak at the book). The other thing that evaluates to NaN is trying to convert a string that isn't purely numbers into a number. See? Just trying to talk about this stuff is confusing. So "23" is a string because of the quotes, right? But it's all numbers, so that will convert if you try to subtract or multiply with it. Something like "monkey" though, will evaluate to NaN if you try to do math with it.

Now so far I'm with them. There are other ways to handle something like that, but this is the JS approach. That's fine. But then the rough patches start. For one, NaN isn't equal to anything, not even itself. So I wanted to try this for funsies, so I whipped up a quick page and script that would assign 0/0 to a variable, then compare the variable to itself, and spit out true or false. Sure enough, it's false. And that means that you can't even test for it how you normally would. If you need to check for null or undefined, you can just use the comparison operator. If you try that with NaN, you get false, because NaN isn't equal to anything. And the best part of all? If you use a function to test what type NaN is, it's a number. Yes, Not a Number is a number. This actually made me laugh when I read it. I have to admit, though, it does make sense, just not at first. NaN is supposed to numbers that can't be represented, so it makes sense it would be a number. It also makes sense that it can't equal itself because it can't be represented. It can't hold a value for 0/0 because we can't represent that value. And as soon as it does the comparison it's the new value, it doesn't retain the original formula used to derive it. So even if the formulas are identical it can't know that after the conversion. So even though it makes sense, it's counter intuitive enough to make it seem like 2 guys were working on different things, and realized they needed to stitch the whole thing together, and came up with NaN. I don't think that's the real story, but it reminded me of that thought I had about PHP.

Another example of that is null and undefined. Basically, both mean the same thing. "You made a thing, but haven't put anything in it yet". The rule of thumb is undefined is for empty variables, and null is for empty objects. But why have both? It feels like object guy and variable guy had a meeting when they were done and realized they used different words for the same thing. They will even evaluate to true if you compare them with the == operator. I feel like this isn't a huge deal once you're aware of it, but it is an extra pitfall in something that is, quite frankly, hard enough on its own. But then if this stuff easy then everyone would be doing it, right? Part of me writing this out is so I have to put it in my own words, which should hopefully help me remember it. I feel like my teen years of playing D&D and Magic the Gathering have primed me for remembering seemingly arbitrary and obscure rules, so I may even be ahead of the game on this one. But it never hurts to take extra measures, right? Right.

PrintView Printer Friendly Version

EmailEmail Article to Friend

Reader Comments

There are no comments for this journal entry. To create a new comment, use the form below.

PostPost a New Comment

Enter your information below to add a new comment.

My response is on my own website »
Author Email (optional):
Author URL (optional):
Post:
 
All HTML will be escaped. Hyperlinks will be created for URLs automatically.