Meta

JavaScript: Types

I like JavaScript. It is a language that is both powerful and flexible, but only if you know how to use it. Once you have mastered the JavaScript language you can build almost anything, and you can do so quickly and interactively.

If you think JavaScript is simple or primitive, then you have fallen into a trap. You will find that you have much company in this trap. The so-called JavaScript developers down there may tell you that some other language “X” is superior. They may even tell you that you would be better off with a system that transalates language X into JavaScript. To leave the trap and master JavaScript requires effort and dedication. I know, because back in 1997 I was there.

Since then I’ve learned the depth and breadth of JavaScript on my own, by studying the official specification. You can learn the complete language as well. If your title includes “JavaScript developer”, you should.

In this blog I am going to present short JavaScript program fragment and ask you to predict its output. If you are a JavaScript developer, you will find it to be child’s play. If you are still learning the language, you may have some trouble and I hope you’ll read the explanation that follows.

The following JavaScript code displays an alert box. What will the alert box contain?

var five = 5;
five.three = 3;
alert(five + five.three);

Skip to the end of this article to learn the correct answer. Here’s an explanation of how JavaScript arrives at that answer.

Objects include arrays, functions, and ordinary objects. Numbers may be integers or floating point or the special values NaN and Infinity. Strings include the empty string, "". Booleans have only two values: true and false. The last two primitive types are a little unusual: the only value whose type is Null is null, and the only value whose type is Undefined is undefined. All of the types except Object are also called “primitive”. The type of a JavaScript variable is not declared explicitly, it is inferred by the JavaScript runtime. In this case the type of the variable called five is Number because it has been assigned a Number literal.

Just like many other computer languages, JavaScript will implicitly convert the type of a value to suit the operator that is being applied to the value. Unlike many computer languages, JavaScript is very aggressive about this. For example the result of "5" - "3" is the Number 2 because the minus operator converts both of its operands to Numbers. If an operand can’t be converted to a Number, then NaN (“Not a Number”) is used instead. For example "5" - "Fred" is implicitly converted to 5 - NaN, which yields NaN.

The complete set of rules for implicit type conversions isn’t terribly complicated so long as you know what type of operands each operator requires.

The Object and String rules that follow state that initially the Object “value is converted to a primitive”. If the operand’s type must be a Number, this means that the JavaScript engine calls the object’s valueOf() method and if the result is not primitive, then the result is converted to a String with the object’s toString() method. If the operand’s type must be a String, the process begins by calling the object’s toString() method, and if its result is not primitive then the valueOf() method is applied to that. In either case, if the result still isn’t a primitive, then an exception is thrown.

Now that the type conversion rules are clear, let’s return to the example.

var five = 5;
five.three = 3;
alert(five + five.three);

As we noted before, the first line creates a variable called five whose type is Number.

When the property accessor is applied to the variable five, its type is converted to Object. This is called “boxing” and it relies on the Number constructor, which produces an Object, not a Number primitive. The second line of the example is equivalent to this:

(new Number(five)).three = 3;

As you can see, we have not saved a reference to the new Number Object in any variable. After this expression has been evaluated, the Number Object whose three property was set is discarded. The five variable remains unchanged.

The third line’s five.three expression causes another Number Object to be created. Since the new Object has no three property, the special undefined value is returned. The result is equivalent to this:

alert(5 + undefined);

The addition operator converts both of its operands to Numbers. In this case undefined is converted to NaN which yields:

I also find that it’s best to refer to numeric primitives with “number” and numeric objects with “Number” to reduce confusion on this very topic. It’s how JavaScript describes them internally as seen via the typeof operator their internal class property.

August 30, 2012 at 1:09 am, A C R E S T A N said:

Yes, the article is very confusing because of the capital letter the author uses for primitives…
ie: the sentence “the first line creates a variable called five whose type is Number” is wrong! Your code proves it.

Please read also my link, how I write real javaScript class functions, that are derivable without copying (like in extend or simple inheritance) and are based on a (class) function declaration and not an object declaration.

Functions are obviously very important in JavaScript and deserve separate article, but they don’t have separate type. Functions are special objects. Special, but still objects.
Objects, created by different constructors share the same type: Object. It’s easy to check: if Object(a) === a then a is Object and nothing else.

Because of this I don’t like the typeof operator:
it makes the difference in Function and Object and returns a string ‘function’, so it becomes confusing in that typeof says !== ‘object’.
instanceof returns true on Function and Object, but not for primitive types like 5, that is a literal typeof ‘number’ but not a object instanceof Number.

October 05, 2012 at 3:32 am, Max Podriezov said:

I was confused by typeof operator returning “object” for null….. Why ecma doesn’t want o change this to be “null”?

This is a great article. Don’t want to get caught up in the minutia of naming practices.

September 07, 2012 at 5:37 am, Dave Chapman said:

This kind of coding error is exactly why we need better IDE’s that can syntax check code as we type and before we run it… e.g. running this throught the closure compiler produces the following warning:

“JSC_INEXISTENT_PROPERTY: Property three never defined on Number at line 4 character 13
alert(five + five.three);”

If examples from the talk you suggested made you say “Wat?”, you clearly need to read my articles… and spec.

September 08, 2012 at 6:25 pm, simonleung said:

A number can be in “object” type or “number” type.
When a condition must be a Boolean, the result may be different, e.g.
( Number(0) ) => true because Number(0) is an object
( 0 ) => false

The type of null is “object” when using operator ‘typeof’ but (null) is false.

September 30, 2012 at 4:01 am, Max Podriezov said:

Saying that JavaScript is most confusing language is so silly – know your tool, just read the ecma-spec and you will get the power…. Dmitry described the basics, something that everybody should know before starting to code… and still someone is trying to say that we have more than 6 types))) Whats wrong with us? Why everybody think that they know how to code before reading specification? Just read the spec and i am 100% sure u will love JavaScript.

November 12, 2012 at 2:26 am, Thomas said:

(one more) Great Article!

Its much more fun reading your posts than struggling with ECMA 262 😉

Well written and easy to understand!
A good Programmer dont cry “WAT” but read the (f*) spec and try to understand whats going on…

Thanks for great js types explanation! But I’m a bit confused with the following sentence from your article:If the operand’s type must be a String, the process begins by calling the object’s toString() method, and if its result is not primitive then the valueOf() method is applied to that. In either case, if the result still isn’t a primitive, then an exception is thrown.

How does engine know that operand’s type must be a String? For example if I do obj + “5” what is the expected type of obj? Looks like it should be string, right? If so, then I don’t understand why the following code execute valueOf instead of toString: http://jsfiddle.net/podlipensky/Kex6H/1/