Primitives
Let me begin by asking if you knew that there were only 3 primitives or primary types in JavaScript that can hold a value. That’s right, only 3. No more. No less. They are number, string and boolean. These are not objects. I know your dad said everything in JavaScript is an Object . Sorry dad you are wrong . Think of primitives as irreducible atomic constructs that the interpreter natively understands without any translation. When the JavaScript interpreter needs to evaluate an expression, it’s really all about just breaking or reducing it down into primitives and applying operators. That is also where coercion plays a big role with strange concepts like truthy or falsy, (huh ?) but that is the subject of another discussion, and it’s not as bad as it sounds.
Primitives are values like true, 1 or “I am a string” and they are immutable. This means that if you do anything to them a new one is created with the result of whatever you did, and the original remains unchanged. In JavaScript it also means they are copied by value and not by reference. Primitives also don’t have any methods that you can invoke. They don’t have methods ? How come you seem to be able to call methods on number string and boolean? Well, there are these object wrappers called Number(), Boolean() and String(), and these do indeed have methods you can call. If you are calling a method on a string, number or boolean then you are actually calling the wrapper object that was inferred and created by the interpreter at run time. However, you should remember that that the wrapper is a separate thing from the primitive value, something through which you can access the primitive. The wrappers in of themselves are just plain ol’ JavaScript Objects, with methods specific to the primitive type that they are wrapping. You can see these represented in the diagram.
Plain ol’ JavaScript Objects
Now lets talk about the JavaScript Object ? Is that not a primitive or primary type ? Well, no its not. It’s not a primitive type but what we call a composite type. That means we use it to build other things made up of primitives and other composite objects and so on…. It is basically nothing but a kind of lookup table or dictionary in which the keys are property names and the values are, well, other primitives and other objects. Yes even JavaScript Arrays and Functions can be thought of as just objects with special methods to do function and array stuff. A JavaScript Array is not like a C# array. Not at all. It just seems to operate like one at first glance. A JavaScript function is also not like a C# method or static function. It’s a whole different beast with magical powers, but at its heart it’s still just a object like any other, but whose distinguishing trait is the capability to be invoked through the () operator and some interesting semantics regarding the new operator. In JavaScript the gods are indeed human. We need not be afraid.
When we compose any JavaScript object, we are simply adding entries in that lookup table, and like I said earlier, these parts are a combination of either a number, a boolean, a string or another object like function or array. Even global variables are just entries in the global lookup table object, but the interpreter masks that association for you so it just seems like an independent thing. Resolving a variable and its value is basically a lookup operation. Now let’s explore this lookup table metaphor to understand null and undefined. It is, I presume, the reason you are reading this post.
If you should happen to have some lookup table and you attempt to find an entry that cannot be found, then it is most likely that a ‘not found exception’ would be thrown or some indication of “not foundness” would be made known. Right ? That is equivalent to undefined in JavaScript. I like to think of undefined as ‘notfound’. Put it this way: If the value existed and its value was null then the result of a lookup would be null, because the variable and its value could be found. However, uninitialized variables in JavaScript don’t get assigned a default value like in c#, that is why the default value cannot be found, or in other words, it is undefined. This ‘foundness’ or ‘unfoundness’ quality is how I like to explain and differentiate undefined from null. null can be found and incidentally, that is also why typeof(null) is [object]. You can’t find nothing, but you can indicate that nothing was found . Hence null and undefined.
It lives, …sort of
Makes no sense at all, I know. And not very pretty. Talk about cognitive dissonance. But if you think of it in terms of “foundness” … your world might make a little more sense. You might even develop a “foundness” for JavaScript, warts and all .
undefined is like not found
I started by saying that in JavaScript we have numbers booleans and strings as primitives that can have a value or that can have state. But there are two other primitives that do not have state but represent a state. One state is null and the other is a representation for “not found” or undefined. You need this state because of the lookup nature of JavaScript. I hope that helps you to understand the difference between the two. It works for me, even though I concede that it might not withstand the full scrutiny of all you boffins out there. Works for me.