Types in JavaScript
My last few blog posts have focused on changing values from one type to another and the mechanisms that make those coercion operations happen, but I think it's worth taking a step back to fundamentally understand what each of the data types in the language are, what they look like, and when they might get used.
As of ECMAScript Spec Version 12.0, there are eight types within JavaScript. I've seen different numbers at different times and from different sources across the internet, but at the moment of writing, eight types are detailed within the language spec. These are:
undefined
null
Boolean
String
Symbol
Number
BigInt
Object
What follows is by no means comprehensive. There are a lot more details for each of these types, so like in other posts I've included lots of extra resources and further reading. This post is instead a cursory look at the general use cases for each of the eight types in JavaScript at the time of writing this post.
undefined
undefined
is a type that occurs when a variable is declared but not assigned a value. For the undefined
type, its only value is itself: undefined
.
var undefinedThing;console.log(undefinedThing);// expected result: undefined
Alternatively, if you are trying to access non-existent properties on an Object
, you will encounter undefined
:
var person = { name: "Joey",};
console.log(person.age);// expected result: undefined
You can also use the void
operator to always return undefined
. void
does not modify the existing value:
var person = { name: "Joey",};
console.log(void person.name);// expected result: undefined
console.log(person.name);// expected result: "Joey"
While the prevailing pattern is that undefined
is something the language compiler assigns to values that are declared but not given any other value (or otherwise deliberately void
ed), you can deliberately assign undefined
as a value. However, this is an anti-pattern and should be avoided.
var undefinedThing = undefined;console.log(undefinedThing);// expected result: undefined
Speaking of anti-patterns, undefined
is a global identifier, or a variable in the global scope. The initial value of this primitive value is itself, undefined
. Because of this, you are permitted to use undefined
as an identifier. In other words, you can use undefined
as a variable name and override the default value of undefined
:
function badIdeaNeverDoThis() { undefined = 100;}
badIdeaNeverDoThis();// global undefined has been reassigned
Rather than assigning anything the value of undefined
, you should either use null
or the void
operator, and if for some reason you ever find yourself using undefined
as a variable name or reassigning the value of the global undefined
identifier, you should probably re-evaluate what you're trying to do.
undefined
gets treated as Falsy within a Boolean
evaluation:
var undefinedThing;if (undefinedThing) { console.log("Truthy!");} else { console.log("Falsy!");}// expected result: "Falsy!"
You can also use undefined
in conjunction with the strict equality/inequality operators to test whether a variable has a value. Because ===
and !==
do not allow for type coercion in their comparison operations, it is safe to proceed knowing that what you're testing truly does or does not have an assigned value:
var undefinedThing;if (undefinedThing === undefined) { console.log("undefinedThing has not been assigned a value");} else { console.log(`undefinedThing has been assigned the value ${undefinedThing}`);}// expected result: "undefinedThing has not been assigned a value"
You can also use the typeof
operator to check whether a variable has a value:
var undefinedThing;if (typeof undefinedThing === "undefined") { console.log("undefinedThing has not been assigned a value");}// expected result: "undefinedThing has not been assigned a value"
There's a big gotcha to be aware of with typeof
and undefined
though, which is that typeof
doesn't throw any error if you were to do the same with a variable that has not been declared:
// otherUndefinedThing has not been declared at allif (typeof otherUndefinedThing === "undefined") { console.log("otherUndefinedThing has not been assigned a value");}// expected result: "otherUndefinedThing has not been assigned a value"
It's an important distinction that needs to be made between an "undefined" variable and an "undeclared" variable; the former has been declared with a var
or let
keyword (reminder that const
variables must be assigned a value when they are declared or they will throw a SyntaxError
), and the latter has not been declared at all. When you call them outside of any other context, the undefined variable returns undefined
and the undeclared variable throws a ReferenceError
:
var undefinedThing;undefinedThing;// expected result: undefined
otherUndefinedThing;// expected result: ReferenceError: otherUndefinedThing is not defined
typeof undefinedThing;// expected result: "undefined"
typeof otherUndefinedThing;// expected result: "undefined"
It's an unfortunate state of things, since the typeof
operator would indicate that both the undefined variable and the undeclared variable are of the undefined
type and the "not defined" verbiage "ReferenceError: otherUndefinedThing is not defined
is so linguistically similar to "undefined"
. It's grounds for a great deal of confusion.
However, with variables declared with the var
keyword, you can additionally test whether that variable exists in its enclosing context using the in
operator. For variables at the global scope, that is the window
:
var undefinedThing;if (typeof undefinedThing === "undefined" && "undefinedThing" in window) { console.log("undefinedThing has not been assigned a value");}// expected result: "undefinedThing has not been assigned a value"
// otherUndefinedThing has not been declared at allif ( typeof otherUndefinedThing === "undefined" && "otherUndefinedThing" in window) { // this code never runs console.log("otherUndefinedThing has not been assigned a value");}
Per MDN:
A variable that has not been assigned a value is of type
undefined
. A method or statement also returnsundefined
if the variable that is being evaluated does not have an assigned value. A function returnsundefined
if a value was not returned.
null
null
is an assignment value that can be assigned to a variable to represent that that variable holds no value. For the null
type, its only value is itself: null
.
Unlike undefined
, the null
value must be deliberately assigned within the code:
var nullThing = null;console.log(nullThing);// expected result: null
null
gets treated as Falsy within a Boolean
evaluation:
var nullThing = null;if (nullThing) { console.log("Truthy!");} else { console.log("Falsy!");}// expected result: "Falsy!"
When used with null
, typeof
returns "object"
:
var nullThing = null;typeof nullThing;// expected result: "object"
This is commonly seen as a bug within the language, but it's been around for so long that a lot of code in production depends on typeof(null)
to return "object"
. Fixing this bug would create even more bugs and break too much production code to be able to make the case for fixing it.
Per MDN:
The value
null
represents the intentional absence of any object value. It is one of JavaScript's primitive values and is treated as falsy for boolean operations.
Boolean
The Boolean
type represents a logical entity having two possible values: true
or false
. I like to think of primitive Booleans
as being a key to understanding an application's state. For example, determining whether a user is logged in:
var loggedIn = false;
function userLogin() { // Do some authentication work loggedIn = true;}
userLogin();
console.log(loggedIn);// expected result = true
With loggedIn
set to true
, you can put some conditional logic in place to display certain content based on that state:
if (loggedIn) { // display some logged in user content here} else { // display a login form for the not-logged in user here}
This sort of conditional is what the Boolean
type is all about. It's common though to do this kind of check with non-Boolean
values, and this is where Implicit Coercion comes in. When you use a non-Boolean
value in a context that expects a Boolean
, then that non-Boolean
value needs to be coerced to a Boolean
to determine the outcome of that conditional logic.
Roughly speaking, the following values will always coerce to false
, and are thus referred to as "Falsy" values:
undefined
null
+0
,-0
NaN
0n
""
(emptyString
)
All other values and types coerce to true
, and are thus referred to as "Truthy".
See Implicitly Coercing to a Boolean
in my Implicit Coercion blog post for more information.
When used with a Boolean
, typeof
returns "boolean"
:
var bool = true;typeof bool;// expected result: "boolean"
Per MDN:
The
Boolean
object represents a truth value:true
orfalse
.
String
The String
type is any collection of characters contained within single-quotes, ''
, double-quotes ""
, or backticks `` that represent text content.
var str1 = "Hello!";var str2 = "Howdy!";
The single- and double-quotes essentially function the same - the full String
value is wrapped in one or the other in order to construct the String
. Backticks `` are a newer, more special case as they allow a developer to embed expressions within the String
, and the result of that expression gets interpolated when the String
is rendered.
In its simplest use case, this means interpolating a variable's value into the String
by noting it with ${[variable or expression name]}
:
var greeting = "Hello";console.log(`${greeting} world`);// expected result: "Hello world"
The problem this solves is the clunky way in which String
s and variables were historically combined in JavaScript:
var greeting = "Hello";console.log(greeting + " world");// expected result: "Hello world"
Much more sophisticated expressions can also be used:
var age = 17;var ageCheckMessage = `You are ${age < 18 ? "not" : ""} permitted to vote`;console.log(ageCheckMessage);// expected result: "You are not permitted to vote"
In most frontend development work, String
values are the text content that gets embedded on the DOM for the user to consume. Sometimes when data comes out of a database or CMS it needs to be manipulated to fit a design, or various content pieces need to be combined. There are a ton of methods available on the String
value type to do this kind of manipulation, like .slice()
, .substr()
, or .substring()
to isolate smaller portions of a String
or .repeat()
to repeat that String
value.
Backend development isn't too drastically different from this, but you might also encounter the use of String
values as constants to be used across your program. An example of this might be an API key:
Here's some pseudocode for this pattern:
var API_KEY = 'ABCDE12345';
// later on in your programfunction async fetchDataFromSomeApi(url, key) { var options = { url, key, json: true }; var data = await fetch(options);};
var response = fetchDataFromSomeApi('https://apiendpoint.dev/givemedata', API_KEY);
You may also have to coerce other types to String
representations in order to be able to display them properly on the frontend. Read more about explicit coercion to a String
here and implicit coercion to a String
here.
An empty String
, ""
, gets treated as Falsy within a Boolean
evaluation, but all other String
values get treated as Truthy:
var emptyString = "";var notEmptyString = "howdy";
if (emptyString) { console.log("Truthy!");} else { console.log("Falsy!");}// expected result: "Falsy!"
if (notEmptyString) { console.log("Truthy!");} else { console.log("Falsy!");}// expected result: "Truthy!"
When used with a String
, typeof
returns "string"
:
var str = "howdy";typeof str;// expected result: "string"
Per MDN:
The
String
object is used to represent and manipulate a sequence of characters.
Symbol
The Symbol
type is a value that represents a unique identifier. A Symbol
is created using the Symbol()
global function, which accepts a description
as its argument:
var sym = Symbol("description");console.log(sym);// expected result: "Symbol(description)"
The Symbol
type is mainly used to provide unique property keys for an Object
. These Object
properties cannot be accessed or overwritten by other parts of your program. This is very useful when working with a database or importing dependencies then adding your own functionality; by adding a property that is reliably unique, you can ensure that there will not be any code collisions.
Say you're writing a program that registers vehicles in a database, but to help you out you are importing a Vehicle
data model from some library:
// in class-vehicle.jsexport class Vehicle { constructor(make, model, year) { this.make = make; this.model = model; this.year = year; this.id = Math.floor(100000000 + Math.random() * 900000000); } detailCar() { console.log(` make: ${this.make}, model: ${this.model}, year: ${this.year}, id: ${this.id} `); }}
Now in your own program, you import that Vehicle
class:
import { Vehicle } from "./class-vehicle.js";
var car1 = new Vehicle("Toyota", "Corolla", 2000);
car1.detailCar();/* * expected result: * make: Toyota, * model: Corolla, * year: 2000, * id: 986667798 // or some other random number */
However, say you want to add an id
property to car1
. The issue you'll run into by just doing car1.id = [yourdesiredidnumber]
is that you'll be overwriting the id
that comes from the Vehicle
constructor, which may be necessary for that dependency library to work.
import { Vehicle } from "./class-vehicle.js";
var car1 = new Vehicle("Toyota", "Corolla", 2000);
car1.detailCar();/* * expected result: * make: Toyota, * model: Corolla, * year: 2000, * id: 986667798 // or some other random number */
car1.id = "MyDesiredID123";
car1.detailCar();/* * expected result: * make: Toyota, * model: Corolla, * year: 2000, * id: MyDesiredID123 // Uh oh */
A Symbol
allows you to add a property named [id]
that is truly unique, so it will not collide with the id
property you get from the Vehicle
constructor:
import { Vehicle } from "./class-vehicle.js";
var car1 = new Vehicle("Toyota", "Corolla", 2000);
car1.detailCar();/* * expected result: * make: Toyota, * model: Corolla, * year: 2000, * id: 986667798 // or some other random number */
var id = Symbol("vehicleId");car1[id] = "MyDesiredID123";
console.log(car1[id]);// expected result: "MyDesiredID123"
console.log(car1.id);// expected result: 986667798
This is because a Symbol
by design is unique. Even two Symbol
s that share a description will not actually share an identity:
Symbol("howdy") === Symbol("howdy");// expected result: false
Another neat thing about the Symbol
type is that an Object
property whose key is a Symbol
is not discoverable by a for...in
Loop or by Object.keys()
or Object.values()
:
var e = Symbol("someSymbol");var obj = { a: 100, b: "Joey Reyes rules", c: true, d: [1, 2, 3], [e]: "JavaScript Drools",};
for (let key in obj) { console.log(key);}// expected result: "a", "b", "c", "d" - no "e"
Object.keys(obj);// expected result: ["a", "b", "c", "d"] - no "e"
Object.values(obj);// expected result: [100, "Joey Reyes rules", true, [1, 2, 3]] - no "JavaScript Drools"
You can still access the Symbol
directly:
var e = Symbol("someSymbol");var obj = { a: 100, b: "Joey Reyes rules", c: true, d: [1, 2, 3], [e]: "JavaScript Drools",};
console.log(obj[e]);// expected result: "JavaScript Drools"
It's also worth noting that this isn't really a reliable way of stashing away data or functionality you want hidden. Even though the traditional ways of accessing an Object
's keys and values won't expose the Symbol
property, Object.getOwnPropertySymbols()
will:
var e = Symbol("someSymbol");var obj = { a: 100, b: "Joey Reyes rules", c: true, d: [1, 2, 3], [e]: "JavaScript Drools",};
var sneakySymbols = Object.getOwnPropertySymbols(obj);console.log(sneakySymbols);// expected result: [Symbol(someSymbol)]
Here we'll get an array that exposes available Symbol descriptions, and from there we can do:
var e = Symbol("someSymbol");var obj = { a: 100, b: "Joey Reyes rules", c: true, d: [1, 2, 3], [e]: "JavaScript Drools",};
var sneakySymbols = Object.getOwnPropertySymbols(obj);var exposedSymbol = obj[sneakySymbols[0]];console.log(exposedSymbol);// expected result: "JavaScript Drools"
So it's a fair amount of work to get to, but you can still retrieve information in an Object
that's "hidden" as a Symbol
.
All Symbol
s gets treated as Truthy within a Boolean
evaluation:
var sym = Symbol("description");
if (sym) { console.log("Truthy!");} else { console.log("Falsy!");}// expected result: "Truthy!"
When used with a Symbol
, typeof
returns "symbol"
:
var sym = Symbol("description");typeof sym;// expected result: "symbol"
Per MDN:
Symbol
is a built-in object whose constructor returns asymbol
primitive — also called a Symbol value or just a Symbol — that's guaranteed to be unique.Symbol
s are often used to add unique property keys to an object that won't collide with keys any other code might add to the object, and which are hidden from any mechanisms other code will typically use to access the object. That enables a form of weak encapsulation, or a weak form of information hiding.
Numeric Types
Numbers in JavaScript can be represented either by the Number
type or the BigInt
type.
Number
The Number
type is used to represent and manipulate numeric values. Just about all numeric work I've ever done in JavaScript has been with Number
, not with BigInt
.
Number
s are typically created as such:
var num1 = 420;var num2 = 420.0;
Number
s can get used with mathematical operators such as +
, -
, /
, *
, %
and so on, as well as the properties and methods found on the Math
Object
to perform mathematical operations:
// some addition500 + 166;// expected result: 666
// the `max` method from `the` Math objectMath.max(666, 420);// expected result: 666
We can explicitly coerce non-Number
values to Number
representations using the global Number()
function or the parseInt()
and parseFloat()
functions:
var str = "420";
Number(str);// expected result: 420
parseInt(str);// expected result: 420
parseFloat(str);// expected result: 420
We can also implicitly coerce non-Number
values to Number
representations using mathematical operators; note that the +
operator also does String
coercion so its usage for coercing to a Number
has some nuance.
var res1 = 420 - "0";console.log(res1);// expected result: 420;
var arr = ["420"];
var num = 100;
var res2 = arr * num;console.log(res2);// expected result: 42000
See Implicitly Coercing to a Number
in my Implicit Coercion blog post for more information.
0
and -0
get treated as Falsy within a Boolean
evaluation; all other Number
values get treated as Truthy:
var posZero = 0;var negZero = -0;var posNum = 420;var negNum = -666;
if (posZero) { console.log("Truthy!");} else { console.log("Falsy!");}// expected result: "Falsy!"
if (negZero) { console.log("Truthy!");} else { console.log("Falsy!");}// expected result: "Falsy!"
if (posNum) { console.log("Truthy!");} else { console.log("Falsy!");}// expected result: "Truthy!"
if (negNum) { console.log("Truthy!");} else { console.log("Falsy!");}// expected result: "Truthy!"
When used with a Number
, typeof
returns "number"
:
var num = 420;typeof num;// expected result: "number"
Per MDN:
Number
is a primitive wrapper object used to represent and manipulate numbers like37
or-9.25
.
BigInt
The largest numeric value that JavaScript can reliably represent with the Number
primitive is 2^53 - 1, which is also represented by the constant Number.MAX_SAFE_INTEGER
. In order to represent larger integers, JavaScript introduced the BigInt
type.
var bigNum = BigInt(654333333333333333333333333333333333333);console.log(bigNum);// expected result: 654333333333333353170768266086452297728n
BigInt
values are stored as arbitrary-precision integers, whereas Number
values get stored as double-precision 64-bit numbers. Since they are integers, BigInt
values don't suffer from floating-point precision problems that Number
values do, but the usage of BigInt
values is limited by the available memory of the environment they're used in.
MDN lists the differences between Number
and BigInt
, as well as some usage recommendations:
BigInt
cannot be used with methods in the built-inMath
objectBigInt
values cannot be mixed withNumber
values inMath
operations- Do not coerce between
BigInt
andNumber
values, as this can lead to loss of precision - Only use a
BigInt
value when values greater than 2^53 are reasonably expected - Do not use
BigInt
s in cryptographic operations;BigInt
operations are not constant-time and are open to timing attacks - When used on a
BigInt
,JSON.stringify()
will throw aTypeError
; in order to serialize aBigInt
in JSON, you can:- Use
.toString()
- Use
JSON.stringify()
's built-inreplacer
parameter to define howBigInt
gets serialized
- Use
0n
gets treated as Falsy within a Boolean
evaluation; all other BigInt
values get treated as Truthy:
var zeroBigInt = 0n;var posBigInt = 1000n;
if (zeroBigInt) { console.log("Truthy!");} else { console.log("Falsy!");}// expected result: "Falsy!"
if (posBigInt) { console.log("Truthy!");} else { console.log("Falsy!");}// expected result: "Truthy!"
When used with a BigInt
, typeof
returns "bigint"
:
var bigNum = BigInt(654333333333333333333333333333333333333);typeof bigNum;// expected result: "bigint"
Per MDN:
BigInt
is a primitive wrapper object used to represent and manipulate primitivebigint
values — which are too large to be represented by thenumber
primitive.
Object
The last data type (as of now) is Object
. Object
s are fundamental to JavaScript, and there is not enough space here to cover all of the nuances about this data type. I highly recommend Kyle Simpson's book, this & Object Prototypes or the second edition update, Objects & Classes for a much richer dive into the Object
type and the role that it plays in the language. What I present here is a very, very cursory example of common usage.
The Object
type is used to store various keyed collections and represents data that is generally much more complex than primitives, like a Boolean
or a String
. If you have followed along on this blog for some time, you've seen countless examples of Object
s throughout my blog posts. An Object
constructed through literal syntax looks something like:
var obj = { a: 100, b: "Joey Reyes rules", c: true, d: [1, 2, 3], e: function sayHi() { console.log("Hi"); }, f: { a: "JavaScript Drools", },};
Within a set of curly braces {}
, there are keys or properties. Here these would be a
, b
, c
, d
, and e
. The properties are typically followed by a colon :
, and on the other side of that colon is the value that is assigned to that key or property. In this example these would be 100
, "Joey Reyes rules"
, true
, the sayHi()
function, and the { a: "JavaScript Drools" }
Object
.
The values within an Object
can be accessed through dot notation:
var obj = { a: 100, b: "Joey Reyes rules", c: true, d: [1, 2, 3], e: function sayHi() { console.log("Hi"); }, f: { a: "JavaScript Drools", },};
obj.a;// expected result: 100
obj.b;// expected result: "Joey Reyes rules"
obj.c;// expected result: true
obj.d;// expected result: [1, 2, 3]
obj.e;// expected result: function sayHi() { console.log("Hi"); }
obj.f;// expected result: { a: "JavaScript Drools" }
It's probably clear then by now that typically an Object
will represent some kind of collection of common data and functionality, and the values within an Object
can be any other data type discussed earlier in this post, as well as other Object
s and Array
s. You can see an Array
in obj.d
and an Object
in obj.f
. You can get to specific data items within those values with further dot notation or (for Array
s) bracket notation:
var obj = { a: 100, b: "Joey Reyes rules", c: true, d: [1, 2, 3], e: function sayHi() { console.log("Hi"); }, f: { a: "JavaScript Drools", },};
obj.d[0];// expected result: 1
obj.f.a;// expected result: "JavaScript Drools"
All Object
s get treated as Truthy within a Boolean
evaluation:
var obj = {};
if (obj) { console.log("Truthy!");} else { console.log("Falsy!");}// expected result: "Truthy!"
The exception to this is a peculiar case called document.all
, which is an old, nonstandard, deprecated part of legacy web browsers. The spec says that this very special Object
will only return true
when compared with null
or undefined
, making it essentially a Falsy Object
. Coercing document.all
to a Boolean
was a method used to determine whether the code was running in an old, nonstandard version of Internet Explorer.
var obj = document.all;
if (obj) { console.log("Truthy!");} else { console.log("Falsy!");}// expected result: "Falsy!"
When used with an Object
, typeof
returns "object"
:
var obj = { a: 100, b: "Joey Reyes rules", c: true, d: [1, 2, 3], e: function sayHi() { console.log("Hi"); }, f: { a: "JavaScript Drools", },};
typeof obj;// expected result: "object"
Per MDN:
The
Object
type represents one of JavaScript's data types. It is used to store various keyed collections and more complex entities.
Array
Array
s themselves are a special type of Object
. You may have noticed that a typical Object
uses String
or Symbol
values for its key/property names, and that these property names can be just about anything you want and be put into any order that you want. An Array
on the other hand uses Number
s as its keys. This special numbered key is called an index, and the order of data corresponds to that data's index. As such, Array
s present a more formal organization than other typical Object
s.
All Array
s get treated as Truthy within a Boolean
evaluation:
var arr = [];
if (arr) { console.log("Truthy!");} else { console.log("Falsy!");}// expected result: "Truthy!"
When used with an Array
, typeof
returns "object"
:
var obj = { a: 100, b: "Joey Reyes rules", c: true, d: [1, 2, 3], e: function sayHi() { console.log("Hi"); }, f: { a: "JavaScript Drools", },};
typeof obj.d;// expected result: "object"
Per MDN:
The
Array
object, as with arrays in other programming languages, enables storing a collection of multiple items under a single variable name, and has members for performing common array operations.
Function
function
s can also be put into Object
s, and typically are done so to help encapsulate functionality common to the data that that Object
represents. You can see a function
in obj.e
. You may note that calling obj.e
like the other obj
properties simply lists out the contents of that function
. But we can also call the function
like so:
var obj = { a: 100, b: "Joey Reyes rules", c: true, d: [1, 2, 3], e: function sayHi() { console.log("Hi"); }, f: { a: "JavaScript Drools", },};
obj.e();// expected result: "Hi"
Function
s themselves are also a special type of Object
, called a "callable object". They have special behavior that allows them to be called, meaning the statements within the function body are told to run. But beyond that they can have properties and methods just like any other regular Object
s.
All Function
s get treated as Truthy within a Boolean
evaluation:
function someFunc() { console.log("hi");}
if (someFunc) { console.log("Truthy!");} else { console.log("Falsy!");}// expected result: "Truthy!"
When used with a Function
, typeof
returns "function"
:
var obj = { a: 100, b: "Joey Reyes rules", c: true, d: [1, 2, 3], e: function sayHi() { console.log("Hi"); }, f: { a: "JavaScript Drools", },};
typeof obj.e;// expected result: "function"
Per MDN:
Generally speaking, a
function
is a "subprogram" that can be called by code external (or internal in the case of recursion) to thefunction
. Like the program itself, afunction
is composed of a sequence of statements called the function body. Values can be passed to afunction
, and thefunction
will return a value.In JavaScript,
functions
are first-classobject
s, because they can have properties and methods just like any otherobject
. What distinguishes them from otherobject
s is thatfunction
s can be called.
Summary
undefined
is a type that occurs when a variable is declared but not assigned a value. For theundefined
type, its only value is itself:undefined
null
is a value that can be assigned to a variable to represent that that variable holds no value. For thenull
type, its only value is itself:null
- The broad distinction between
undefined
andnull
is one of intention:null
denotes that the developer intends for there to be no other value, andundefined
denotes that a value has not been assigned yet
- The broad distinction between
- The
Boolean
type represents a logical entity having two possible values:true
orfalse
- The
String
type is any collection of characters contained within single-quotes,''
, double-quotes""
, or backticks `` that represent text content - The
Symbol
type is a value that represents a unique identifier. ASymbol
is mainly used to provide unique property keys for anObject
; it's a way to avoid naming collisions and to create "hidden" properties on anObject
- Numbers in JavaScript can be represented either by the
Number
type or theBigInt
type.- The
Number
type is used to represent and manipulate numeric values.Number
s can get used with mathematical operators and methods from theMath
Object
to perform mathematical operationsNumber
values get stored as double-precision 64-bit numbers; because of this theNumber
type can suffer from floating-point precision problems- The largest numeric value that JavaScript can reliably represent with the
Number
primitive is 2^53 - 1 - The smallest numeric value that JavaScript can reliably represent with the
Number
primitive is -(2^53 - 1)
- The
BigInt
type is used to represent numeric values that are larger than what can be represented by theNumber
typeBigInt
values are stored as arbitrary-precision integers, so they don't suffer from floating-point precision problems, but their usage is limited by available memoryBigInt
cannot be used with methods in the built-inMath
object, nor can it be mixed withNumber
values in mathematical operations
- The
- The
Object
type is used to store various keyed collections of data; this data can be comprised of the other types found in the JavaScript language, and generally theObject
represents data and functionality that are conceptually related- There are a few special types of
Object
s that are given some special functionality or organization, namelyArray
s andFunction
s:- An
Array
is anObject
that uses sequential numeric indexing instead of named properties to achieve a more formal organization pattern to the data that it contains - A
Function
is anObject
that contains "callable" behavior
- An
- There are a few special types of
Sources / Further Reading
- JavaScript data types and data structures on MDN
- 6 ECMAScript Data Types and Values in ECMAScript Spec Version 12.0
- 13.5.3 The
typeof
Operator in ECMAScript Spec Version 12.0 - How many data types are there in JavaScript, what are they, and what is considered a type? thread on Stack Overflow
undefined
on MDNnull
on MDN- Undefined vs. Null by Joey Reyes
Boolean
on MDNString
on MDNSymbol
on MDN- Symbol type on javascript.info
- Using symbols to create (sort of) private properties on mitya.uk
Number
on MDNBigInt
on MDN- BigInt Vs Number in JavaScript on TekTutorialsHub
Object
on MDNArray
on MDN- Functions on MDN