JavaScript for C# Programmers: Types

When I was learning JavaScript, I found I was being tripped up by a whole bunch of invalid assumptions. I was being lulled into a false sense of security by the very familiarity of the C-like structures and syntax. I was also being tripped up by the parts of JavaScript which are just plain awful and that should be avoided at all costs. Despite these bad parts of JavaScript, the main problem was: it's got the word Java in the name, so it must work like Java, and since Java and C# are very close, it must work like C#. Right? Right! Wrong, and hence this new occasional series where I talk about the things which tripped me up.

This episode: the types in JavaScript.

There are only six types in JavaScript. They are: boolean, number, string, null, undefined, and object. The object type includes arrays, functions, dates, other built-in objects, and objects you create yourself. Having just said all that, in JavaScript you don't explicitly state what type a variable is, it's inferred at run-time.

In particular, you won't find some types that you're very familiar with in C#: class, interface, delegate, enum, struct and so on. It's looking a bit bare in the JavaScript type cupboard.

Primitive types

Let's look at the primitive types first of all, that is, everything but objects.

The boolean type has just two values: true and false. We're doing pretty well so far; nothing surprising at all. The constructor function (we'll talk about what this is in a later episode) is Boolean. The typeof operator, applied to a boolean value, returns the string value "boolean".

Numbers, though, are surprising. Unlike C# with its plethora of different numeric types, its bytes, its longs, its floats, and so on, there is only one number type in JavaScript, the 64-bit floating-point double. Specifically, there are no integers. Beware of this; I'll admit I found it astonishing at first. Even if you assign an integer value to a variable, it will be stored as a double value, not as an integer of some integral type. In particular, beware of using equality when comparing two variables that contain numbers; remember the old trick about comparing them to be equal to a certain tolerance (usually known as epsilon).

(Aside: If you are very rigorous about maintaining integer values in the variables you are comparing, you'll find you can compare as you'd expect. Integer values are stored exactly in a double, up to 253.)

There are two "special" number values: NaN and Infinity. The first is a number that's generated from some expression that doesn't produce a normal number, such as 0 divided by 0, or converting a string value that isn't a number to a number. NaN is a strange beast indeed: it is not equal to any other number, including itself. You can test for a variable being NaN by using the special function isNaN(). The second special value is used when a computation exceeds the maximum value allowable in a double (about 1.8 x 10308). You can test for this by using the function isFinite(), which returns true if the value is not NaN and is not Infinity, false otherwise. So, in particular, if isFinite() returns false, you would have to test the value for being a NaN before you could conclude that it was Infinity. There is a gotcha though, the parameter to isFinite() will be converted to a number first if needed (the same goes for isNaN() by the way) — so, for example, isFinite("42") will return true — and therefore you should write and use your own isFiniteNumber() function:

function isFiniteNumber(value) {
    return ((typeof value === "number") && isFinite(value));
}

But wait: we're not done yet. Just to make it very peculiar, JavaScript has the same bit-twiddling operators that C# has, operators like &, |, ^, <<, and >>. Since these don't really make sense on a floating point value, the interpreter will coerce (it's not a cast, but a lopping off of the fractional part and any bits above the 32nd) the arguments into 32-bit integers, perform the operation, and then store the result back into a floating-point value. One easy consequence of this is that expressions with these bitwise operators run much slower than you think. Essentially, you should only use them when you really have to.

The constructor function is Number. The typeof operator, applied to a number value, returns the string value "number".

Strings are pretty much like .NET strings: a sequence of 16-bit Unicode characters. You can define them by surrounding the text with either single or double quotes, and that should give you a hint that JavaScript does not have any char type. If you want a variable that's a single character, merely create a string of length 1. When defining a string, the backslash is the escape character, like in C#. There are a whole set of methods and properties defined for strings, with length being an important one.

The constructor function is String. The typeof operator, applied to a string value, returns the string value "string".

The null type is a peculiar one, it has only one value (compare, for example, with boolean's two), null. This value can be assigned to any variable or property, and means that it has "no value", pretty much like it does in C#. There is no constructor function for null. The typeof operator, applied to a null value, returns the string value "object". This is, to say the least, annoying since it should return "null". In some sense, then, it's very hard to justify whether null is a real type or not.

The undefined type is also a type with just one value, undefined. It means that the variable or property does not exist. For a variable it can also mean that the variable was declared but never assigned a value (if a variable doesn't have a value, there's no way to discern what type it could be, therefore its type is undefined).

For C# programmers, this is a weird one because we're so used to the compiler telling us that something we're referencing does not exist. However, in JavaScript, because it is a dynamic language, we can write and execute code that makes reference to variables and properties that don't exist. If we're at all worried in our code about whether a variable or property hasn't been set or declared yet, we should take the time and write the code to check.

There is no constructor function for undefined. The typeof operator, applied to an undefined value, returns the string value "undefined". This is the accepted way to find out whether a variable or property has been defined yet, rather than simply comparing the identifier to the undefined value.

Major bizarre issue: unlike null, undefined is not a keyword in the language. The interpreter will let you declare and set undefined to 42, for example, with nary a peep. Your code (and other third party code), is likely to start failing in very bizarre ways if you do so, so the recommendation is, don't do it. (Well, OK, try it once and see what effects you can provoke.)

Objects

Objects we'll get to in another episode.

Some experiments

By the way, in order to play around with JavaScript, the easiest way is to use Firefox and install the Firebug add-in. Open up Firebug (F12). Firebug has a Console tab that gives you a command line (see here for details) where you can type in some JavaScript and run it immediately. Try this bit of code:

var a;
console.log(typeof a);
console.log(typeof b);

Run it and you should see:

undefined
undefined

in the output window. (console.log() is a special function injected by Firebug to write values to the Console window.) a has been declared, but, since it doesn't have a value, the only thing we can say about its type is that it's undefined; b, on the other hand, hasn't been declared at all.

Try out the function I declared above, with some tests:

function isFiniteNumber(value) {
    return ((typeof value === "number") && isFinite(value));
}

console.log(isFiniteNumber(42));
console.log(isFiniteNumber(42.123));
console.log(isFiniteNumber(Infinity));
console.log(isFiniteNumber(NaN));
console.log(isFiniteNumber("42"));
console.log(isFiniteNumber("42.123"));
console.log(isFiniteNumber("no way"));
console.log(isFiniteNumber(false));

And you should get: true, true, with the rest false.  Edit the tests to use the bare isFinite() function, and compare the results.

I said above that typeof null was equal to "object". How then can we ascertain whether a variable is null or not? There is no built-in isNull() function. Actually it's quite simple: we merely need to compare the variable to cd:null:

function isNull(value) {
    return value === null;
}

Try it out by using this code.

var c = null;
console.log(isNull(null));
console.log(isNull(c));
console.log(isNull(""));
console.log(isNull(42));

By the way, you may have noticed that I'm using === and not == for comparing equality. The reason why is a topic for another time, but trust me, it's one of those differences between C# and JavaScript you'll have to get used to and that will trip you up no end.

Album cover for En Attendant Cousteau Now playing:
Jarre, Jean Michel - En Attendant Cousteau
(from En Attendant Cousteau)


Loading similar posts...   Loading links to posts on similar topics...

5 Responses

 avatar
#1 Paul St. Amant said...
08-Feb-09 5:48 AM

Thanks for the tutorial, Julian. Lots of times it is trial and error for me when coding in JavaScript, but this helps.

#2 Dew Drop - Weekend Edition - February 7-8, 2009 | Alvin Ashcraft's Morning Dew said...
08-Feb-09 7:18 PM

Pingback from Dew Drop - Weekend Edition - February 7-8, 2009 | Alvin Ashcraft's Morning Dew

julian m bucknall avatar
#3 julian m bucknall said...
09-Feb-09 7:52 PM

Paul: Glad you liked the initial episode. I've just posted episode 2 on objects. Slowly but surely we're getting to the really interesting stuff...

Cheers, Julian

 avatar
#4 Sai Gudigundla said...
09-Feb-09 9:36 PM

Those are some really interesting as well as important points. Coming from .NET background, this was very helpful to me. Thanks for putting it together.

julian m bucknall avatar
#5 julian m bucknall said...
09-Feb-09 10:10 PM

Sai: Great stuff; glad the series is proving useful. Stay tuned for more...

Cheers, Julian

Leave a response

Note: some MarkDown is allowed, but HTML is not. Expand to show what's available.

  •  Emphasize with italics: surround word with underscores _emphasis_
  •  Emphasize strongly: surround word with double-asterisks **strong**
  •  Link: surround text with square brackets, url with parentheses [text](url)
  •  Inline code: surround text with backticks `IEnumerable`
  •  Unordered list: start each line with an asterisk, space * an item
  •  Ordered list: start each line with a digit, period, space 1. an item
  •  Insert code block: start each line with four spaces
  •  Insert blockquote: start each line with right-angle-bracket, space > Now is the time...
Preview of response