Types
JavaScript has eight built-in types, null, undefined, boolean, number, bigint, string, object, and symbol.
Essential:
github.com/getify/You-Dont-Know-JS
Description:
Programming languages all have built-in data structures, but these often differ from one language to another. JavaScript is a dynamic language with dynamic types, and variables in JavaScript are not directly associated with any particular value type, as any variable can be assigned (and re-assigned) values of all types. It is also a weakly typed language, which means it allows implicit type conversion when an operation involves mismatched types, instead of throwing type errors.
Table of Contents
- 1. Introduction
- 2. Creating a Value
- 3. Native Constructors
- 4. Boxing
- 5. Inspecting
- 6. Documentation
- 7. Related notes
1. Introduction
Usually, we understood JavaScript types as follows:
Remember, however, that in JavaScript, the Number
type cannot safely represent integer values larger
than 253. This limitation forced developers to use inefficient workarounds and third-party libraries
until they incorporated BigInt
as a numeric data type intended to address that problem.
Name | Description |
---|---|
bigint | Stores integer values that are too big to be represented by a normal JavaScript Number. |
Note: Detailed information in the following section:
2. Creating a Value
A value can be created in 2 different ways:
Form | Example |
---|---|
Literal form | const strPrimitive = "abc"; |
Constructor form | const strObject = new String("abc"); |
Using the constructor form results in an object wrapper around the primitive value. This gives access
to the helpful properties and methods such as toUpperCase
for a string:
Example:
index.js
--------
// Literal form.
const strPrimitive = "abc";
index.js
--------
// Constructor form.
// Use the 'new' keyword and call a native constructor.
const strObject = new String("abc");
index.js
--------
// toUpperCase example.
const strObject = new String("abc");
console.log(strObject.toUpperCase())
// Output: ABC
3. Native Constructors
Each native constructor has its own prototype object. These contain properties and methods unique to
their object subtype. For example: String.prototype.toUpperCase
. When the constructor form is used,
the returned object’s prototype property is set constructor’s prototype object. This is how you get
access to the properties and methods.
Date
The Date(..)
constructor accepts optional arguments to specify the date/time to use. Format used below is
ISO 8601 format - YYYY-MM-DDTHH:mm:ss.sssZ (international standard).
Example:
index.js
--------
// Create date object of today.
const today = new Date()
console.log(today)
// Create date object of specified date.
// Argument is in ISO 8601 format (time can be omitted).
const july4th2020Midnight = new Date('2020-07-04');
console.log(july4th2020Midnight)
// Get Unix timestamp (the number of seconds since Jan 1, 1970).
// Value is in milliseconds.
const todayTimestamp = new Date().valueOf() // or Date.now()
console.log(todayTimestamp)
// Get date in ISO 8601 string format.
const iSO8601 = new Date().toISOString()
console.log(iSO8601)
// Determine if a date is valid.
function isValidDate(date) {
return date instanceof Date && !isNaN(date);
}
// Output:
// 2024-09-01T22:00:47.923Z
// 2020-07-04T00:00:00.000Z
// 1725228047923
// 2024-09-01T22:00:47.923Z
Error
An error object captures the current execution stack context into the returned object. Stored in property stack
.
This includes the function call-stack and the line-number where the error object was created.
Example:
index.js
--------
function func(x) {
if (!x) {
throw new Error("x wasn't provided");
}
}
func()
// Output:
// Error: x wasn't provided
// As for the syntax, remember:
index.js
--------
new Error()
new Error(message)
new Error(message, options)
new Error(message, fileName)
new Error(message, fileName, lineNumber)
Error()
Error(message)
Error(message, options)
Error(message, fileName)
Error(message, fileName, lineNumber)
RegExp
If you require a variable in a regex, it must be created using the constructor form.
Example:
index.js
--------
const url = 'https://google.com'
const name = "google";
const namePattern = new RegExp(`\b(?:${name})+\b`, "ig");
console.log(url.match(namePattern))
index.js
--------
// As for some other examples:
const regex1 = /\w+/;
const regex2 = new RegExp('\\w+');
console.log(regex1);
// Output: /\w+/
console.log(regex2);
// Output: /\w+/
console.log(regex1 === regex2);
// Output: false
Number
JavaScript uses binary floating-point numbers. This can result in the following bugs:
Output | Example |
---|---|
false | const result = 0.1 + 0.2 === 0.3; console.log(result) |
The representations for 0.1 and 0.2 are not exact. When added, the result isn’t 0.3
, it closer to 0.30000000000000004
.
Number.EPSILON
is predefined with this tolerance value that can be used as a workaround:
Output | Example |
---|---|
true | const result = 0.1 + 0.2 - 0.3 < Number.EPSILON; console.log(result) |
Special Values
Honorable mentions:
▪ NaN
- Not a Number
▪ +Infinity
▪ -Infinity
▪ -0
Output | Example |
---|---|
true | const result = Number.isNaN(1 / "a") console.log(result); |
4. Boxing
A primitive like “abc”
is not an object. However, you can call methods on it like "abc".length
. This is possible through a
technique called boxing. When the interpreter sees a property or method call on a primitive, it calls the constructor form
and passes in the primitive value, creating an object. This object has properties and methods linked to it via the prototype chain.
5. Inspecting
Primitives
The typeof
operator inspects the type of the given value and returns one of seven string values (except for null
).
Example:
index.js
--------
console.log(typeof null)
console.log(typeof undefined)
console.log(typeof true)
console.log(typeof 42)
console.log(typeof "42")
console.log(typeof { foo: "bar" })
console.log(typeof Symbol())
// Outputs:
// object
// undefined
// boolean
// number
// string
// object
// symbol
index.js
--------
// To test for a null value using its type:
const a = null;
console.log(!a && typeof a === "object")
// Output: true
Note: variables don’t have types. Only values do. When using typeof
against a variable, it is like asking: “What’s the type of the
value in this variable?”
Object Subtypes
Let’s analyze a couple of cases now:
▪ [[Class]]
Objects are tagged with an internal [[Class]]
property. A classification (not related to class-oriented coding) corresponding to the built-in
native constructor. It can only be accessed through Object.prototype.toString(..)
:
Example:
index.js
--------
console.log(Object.prototype.toString.call([]))
console.log(Object.prototype.toString.call(/regex-literal/i))
console.log(Object.prototype.toString.call("abc"))
console.log(Object.prototype.toString.call(42))
console.log(Object.prototype.toString.call(true))
console.log(Object.prototype.toString.call(null))
console.log(Object.prototype.toString.call(undefined))
// Outputs:
// [object Array]
// [object RegExp]
// [object String]
// [object Number]
// [object Boolean]
// [object Null]
// [object Undefined]
▪ instanceof
The instanceof
operator tests to see if the prototype property of a constructor appears anywhere in the prototype chain of an object:
Example:
index.js
--------
const strPrimitive = "abc"
console.log(typeof strPrimitive)
console.log(strPrimitive instanceof String)
const strObject = new String("abc");
console.log(typeof strObject)
console.log(strObject instanceof String)
// Outputs:
// string
// false
// object
// true
index.js
--------
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
const auto = new Car('Honda', 'Accord', 1998);
console.log(auto instanceof Car);
// Output: true
console.log(auto instanceof Object);
// Output: true
6. Documentation
For a better understanding of types, remember that websites such as:
▪ w3schools, or
will always be there to offer you some proper insight.