Primitive Values vs. Non-Primitive Values in JavaScript

In JavaScript we have values. A value is a thing. There are many types of values, including objects, arrays, functions, numbers, strings, and booleans. To differentiate between the nature of values, we have a term called data types

In JavaScript there are two types of data types:

  • Primitive values
  • Non-primitive values

Okay, let’s talk about the difference between primitive and non-primitive values in JavaScript.

Primitive Values

Primitive values are things like numbers, strings, boolean, and undefined.

Try printing out the following primitive values in your console:

console.log(4)
console.log('Johnny')

As you can see, the output you get from printing out primitive (simple) values is predictable and not hard to reason about. You ask your console to print out 4, and you get 4, you ask it to print out Johnny, and you get Johnny.

Why are they called primitive values? Because they’re simple (simple values would’ve been a better term for them if you ask me). They’re simple (primitive) in the sense that they are the type of data value that don’t contain properties — unlike non-primitive values which are more “complex” data types, and which we’ll discuss in a moment.

Non-Primitive Values

aka Complex/Special Values

In JavaScript, objects and functions are considered non-primitive values.

You’ll sometimes hear non-primitive values referred to as:

  • object references
  • complex data types
  • special values

These are just alternative ways of referring to values that are not primitive. Yes, it’s annoying with all those synonyms, but you must be aware of them. You can read entire articles on the web that deal with this topic, which only uses one of these terms. A little later you’ll read an article by a different author who uses another term, and then you’ll wonder if you’re even reading about the same language.

Unlike primitive values, non-primitive values do contain properties,

Objects

Try printing out the following in your console:

console.log({}) 
console.log([]) 

Do you notice something different about this output compared to the primitive value examples earlier?

We can click and expand on these outputs. Try clicking on the arrow next to each output (just click one time on each) and see what happens.

Aha, now each has a name. The first is called Object, the second is called Array.

Note: if you’re using Firefox, you might not have to click on the arrow to unveil the data type.

The above are both objects. An array is a type of object in JavaScript — an array object — but it can do different things than regular objects.

To prove that arrays are indeed objects in JavaScript, run the typeof operator on the examples above, like this:

console.log(typeof {}) // object
console.log(typeof []) // object

Yup, they’re both objects.

Okay, now try clicking on the arrows next to your object and array object again, and see what happens.

Holy crap, now things don’t look so simple anymore, do they?

What you’ve uncovered, are all the different property types that regular objects and arrays (a type of object) contain respectively.

Don’t worry about understanding any of this stuff right now, my point is only to show you that objects are not simple value types (they are non-primitive) because they can do a lot of things, unlike primitive values.

Functions

So far you’ve seen objects (regular objects {} & array objects []), now let’s take a look at functions. Try printing out the following in your console:

console.log(function doSomething() { })

If you’re using Chrome, you probably won’t get an expandable output — I don’t know why Google/Chrome designed it like this. If however you try printing out the line above in Firefox, you’ll get a detailed output like this:

Firefox JavaScript console output of an empty function

As you can see functions also have properties but different types than objects.

  • arguments: null — we have no arguments/parameters inside the ().
  • caller: null — we don’t call the function from anywhere
  • length: 0 we have no arguments (zero).
  • name: "doSomething" — the name of our function.

You also have access to the prototype: Object and <prototype>: function () which will unveil a lot more info about functions, just like you saw earlier with objects.

Wait, why does it say prototype: Object? Is a function considered an object?

In JavaScript, every non-primitive value type is to some extent considered an object, including functions (and arrays, as you saw earlier). More specifically, in JavaScript, a function is a function object — a special type of object that can be called with the () syntax, as you saw in the doSomething() example.

Now it probably makes more sense to you why I mentioned earlier that non-primitives are sometimes referred to as object references.

Try running the typeof operator on your function and see what happens:

console.log(function doSomething() {})

It outputs function...

Are you surprised by this?

If everything in JavaScript is an object, why does it output function as the type?

Well, look at the screenshot from earlier again:

Firefox JavaScript console output of an empty function

It says that the function has both a function prototype and an Object prototype.

What happens, and let me make this clear, as I understand it is that in JavaScript the function prototype inherits from the Object prototype.

So a function is indeed its own special data type value (with its own prototype) and should be treated as such since it can do different things than regular objects. But a function has its roots in the so-called Object prototype, so even though it’s its own thing, it still falls under the object umbrella.

Summary

Because of the wide range of options we have with objects and functions we call them non-primitive data types (“complex”) unlike primitive data types (“simple”) such as number and strings, which have limited options in comparison.