JavaScript for impatient programmers (beta)
Please support this book: buy it or donate
(Ad, please don’t block.)

10. Values

In this chapter, we’ll examine what kinds of values JavaScript has.

We’ll occasionally use the strict equality operator (===), which is explained in the chapter on operators.

10.1. What’s a type?

For this chapter, I consider types to be sets of values. For example, the type boolean is the set { false, true }.

10.2. JavaScript’s type hierarchy

Figure 5: A partial hierarchy of JavaScript’s types. Missing are the classes for errors, the constructor functions associated with primitive types, and more. The diagram hints at the fact that not all objects are instances of Object.
Figure 5: A partial hierarchy of JavaScript’s types. Missing are the classes for errors, the constructor functions associated with primitive types, and more. The diagram hints at the fact that not all objects are instances of Object.

Fig. 5 shows JavaScript’s type hierarchy. What do we learn from that diagram?

10.3. The types of the language specification

The ECMAScript specification only knows a total of 7 types. The names of those types are (I’m using TypeScript’s names, not the spec’s names):

10.4. Primitive values versus objects

The specification makes an important distinction between values:

In contrast to Java (that inspired JavaScript here), primitives are not second-class citizens. The difference between them and objects is more subtle. In a nutshell, it is:

Next, we’ll look at primitive values and objects in more depth.

10.4.1. Primitive values

10.4.1.1. Primitives are immutable

You can’t change, add or remove the properties (fields) of primitives:

let num = 123;
assert.throws(
  () => { num.foo = 'abc' },
  {
    name: 'TypeError',
    message: "Cannot create property 'foo' on number '123'",
  }
);
10.4.1.2. Primitives are passed and compared by value

Primitives are passed and compared by value. That means: Variables (incl. parameters) store the primitives themselves and when comparing primitives, we are comparing their contents.

The following code demonstrates comparing by value:

assert.ok(123 === 123);
assert.ok('abc' === 'abc');

To see what’s so special about this way of comparing, read on and find out how objects are compared.

10.4.2. Objects

Two common literals for creating objects, are:

10.4.2.1. Objects are mutable by default

By default, you can freely change, add and remove the properties of objects:

const obj = {};

obj.foo = 'abc'; // add a property
assert.equal(obj.foo, 'abc');

obj.foo = 'def'; // change a property
assert.equal(obj.foo, 'def');
10.4.2.2. Objects are passed and compared by reference

Objects are passed and compared by reference. That means: Variables (incl. parameters) hold (transparent) references to objects on the heap (think shared main memory). When comparing objects, we are comparing references. Each object literal creates a fresh object on the heap and returns a reference to it.

The following code demonstrates comparing by reference:

const obj = {}; // fresh empty object
assert.ok(obj === obj);
assert.ok({} !== {}); // two fresh, different objects

The following code demonstrates passing by reference:

const a = {};
// Pass the reference in `a` to `b`:
const b = a;

// Now `a` and `b` point to the same object
// (they “share” that object):
assert.ok(a === b);

// Changing `a` also changes `b`:
a.foo = 123;
assert.equal(b.foo, 123);

JavaScript uses garbage collection to automatically manage memory:

let obj = { prop: 'value' };
obj = {};

Now the old value { prop: 'value' } of obj is garbage (not used anymore). JavaScript will automatically garbage-collect it (remove it from memory), at some point in time (possibly never if there is enough free memory).

10.5. Classes and constructor functions

JavaScript’s original factories for objects are constructor functions: ordinary functions that return “instances” of themselves if you invoke them via the new operator.

ES6 introduced classes, which are mainly better syntax for constructor functions.

In this book, I’m using the terms constructor function and class interchangeably.

Classes can be seen as partitioning the single type object of the specification into subtypes – they give us more types than the limited 7 ones of the specification. Each class is the type of the objects that were created by it.

10.6. Constructor functions associated with primitive types

Each primitive type (except for the spec-internal types for undefined and null) has an associated constructor function (think class):

Each of these functions plays several roles. For example, Number:

10.7. The operators typeof and instanceof: what’s the type of a value?

The two operators typeof and instanceof let you determine what type a given value x has:

if (typeof x === 'string') ···
if (x instanceof Array) ···

So how do they differ?

Thus, as a rough rule of thumb: typeof is for primitive values, instanceof is for objects.

10.7.1. typeof

Table 1: The results of the typeof operator.
x typeof x
undefined 'undefined'
null 'object'
Boolean 'boolean'
Number 'number'
String 'string'
Symbol 'symbol'
Function 'function'
All other objects 'object'

Tbl. 1 lists all results of typeof. They roughly correspond to the 7 types of the language specification. Alas, there are two differences and they are language quirks:

  Exercises: Two exercises on typeof

10.7.2. instanceof

This operator answers the question: has a value x been created by a class C?

x instanceof C

For example:

> (function() {}) instanceof Function
true
> ({}) instanceof Object
true
> [] instanceof Array
true

Primitive values are not instances of anything:

> 123 instanceof Number
false
> '' instanceof String
false
> '' instanceof Object
false

  Exercise: instanceof

exercises/operators/instanceof_exrc.js

10.8. Converting between types

There are two ways in which values are converted to other types in JavaScript:

10.8.1. Explicit conversion between types

The function associated with a primitive type explicitly converts values to that type:

> Boolean(0)
false
> Number('123')
123
> String(123)
'123'

You can also use Object() to convert values to objects:

> 123 instanceof Number
false
> Object(123) instanceof Number
true

10.8.2. Coercion (automatic conversion between types)

For many operations, JavaScript automatically converts the operands/parameters if their types don’t fit. This kind of automatic conversion is called coercion.

For example, the multiplication operator coerces its operands to numbers:

> '7' * '3'
21

Many built-in functions coerce, too. For example, parseInt() coerces its parameter to string (parsing stops at the first character that is not a digit):

> parseInt(123.45)
123

  Exercise: Converting values to primitives

exercises/values/conversion_exrc.js

  Quiz

See quiz app.