JavaScript Primitive Data Types
Last updated:
There are 7 built-in primitive data types in JavaScript - they are immutable (their values cannot be changed). All other values are considered objects which are mutable.
-
Number - numeric values, including integers and floating-point numbers.
let answer = 42; let pi = 3.14;
-
String - textual data, enclosed in single quotes (‘’) or double quotes (“”).
let name = "Paul"; let message = 'Hello, World!';
-
Boolean - a logical value, either
true
orfalse
.let isOpen = true; let isClosed = false;
-
Undefined - a variable that has been declared but not assigned a value.
let myVariable;
-
Null - a deliberate null value (represents the absence of a value).
let myObject = null;
-
Symbol (introduced in ECMAScript 2015) - a unique identifier.
let mySymbol = Symbol("mySymbol");
-
BigInt (introduced in ECMAScript 2020) - integer values that are too large to be represented by the Number type.
let myBigInt = 1234567890123456789012345678901234567890n;
Number
Used to represent numeric values, e.g. integer, floating-point, and exponential numbers.
Integers
Whole numbers without any decimal points and can be positive, negative, or zero.
Range: -9007199254740991 to 9007199254740991.
let x = 10 // positive integer
let y = -20 // negative integer
let z = 0 // zero
Operations work as expected:
let sum = 10 + 5 // 15
let multiply = 10 * 5 // 50
let divide = 10 / 5 // 2
let subtract = 10 - 5 // 5
Floating-Points (decimals)
Range: -1.7976931348623157 x 10^308 and 1.7976931348623157 x 10^308.
let x = 3.14 // positive floating-point number
let y = -0.5 // negative floating-point number
let z = 0.0 // floating-point zero
Due to the way they are represented in memory, they can sometimes lead to precision errors, which can be problematic in some calculations.
let sum = 0.1 + 0.2 // 0.30000000000000004
When working with financial data or other types of applications that require high precision, the toFixed() method can be used to round the value to a specified number of decimal places.
let pi = 3.14159;
console.log(pi.toFixed(2)); // 3.14
Exponential Numbers
Written using the letter “e” and used to represent very large or very small numbers:
let x = 5e3 // 5000 (5 times 10 raised to the power of 3)
let y = 5e-3 // 0.005 (5 times 10 raised to the power of -3)
let distanceToSun = 149.6e6 // distance to the sun in kilometers
let hairWidth = 0.003e-3 // width of a human hair in meters
Numeric Type Checks and Conversion
Built-in methods available:
isNaN()
- checks if a value is not a numberparseInt()
- parses a string and returns an integer.
let notANum = "hello";
console.log(isNaN(notANum)); // true
let stringNum = "10";
let num = parseInt(stringNum);
console.log(num); // 10
String
A sequence of characters enclosed within single quotes (‘’) or double quotes (“”). Can be created using the String()
function or using template literals. Template literals allow you to embed expressions, variables, and functions inside a string using the ${}
syntax.
const firstName = 'John'
const lastName = 'Wick'
console.log(`My name is ${firstName} ${lastName}.`)
// Outputs: 'My name is John Wick.'
Strings are immutable but a new string by concatenating two or more strings using the +
operator or the concat()
method.
const str1 = 'hello'
const str2 = 'world'
const str3 = str1 + ' ' + str2 // str3 content is: 'hello world'
const str4 = str1.concat(' ', str2) // str4 content is: 'hello world'
String Methods
-
length - returns the length of a string (number of characters):
const hello = 'hello world'; hello.length // Returns: 11
-
indexOf - returns the position of the first occurrence of a specified value or -1 if not found:
const hello = 'hello world'; hello.indexOf('o') // Returns: 4 hello.indexOf('a') // Returns: -1
-
lastIndexOf - returns the position of the last occurrence of a specified value:
const hello = 'hello world'; hello.lastIndexOf('o') // Returns: 7
-
charAt - returns the character at a specified index:
const hello = 'hello world'; hello.charAt(1) // Returns: 'e'
-
charCodeAt - returns the Unicode value of the character at a specified index:
const hello = 'hello world'; hello.charCodeAt(1) // Returns: 101
-
includes - checks if contains a specified value - returns a boolean:
const hello = 'hello world'; hello.includes('world') // Returns: true
-
startsWith - returns true if a string starts with a specified value:
const hello = 'hello world'; hello.startsWith('hello') // Returns: true
-
endsWith - returns true if a string ends with a specified value:
const hello = 'hello world'; hello.endsWith('world') // Returns: true
-
substring - returns a portion of a string between two specified indices:
const hello = 'hello world'; hello.substring(0, 5) // Returns: 'hello'
-
slice - returns a portion of a string based on start and end positions:
const hello = 'hello world'; hello.slice(0, 5) // Returns: 'hello'
If the second argument is omitted, it will return the rest of the string:
hello.slice(1) // returns: 'ello world'
If the second argument is smaller than the first, will return an empty string:
hello.slice(2,1) // returns: ''
If the second argument is negative, will discount characters from the end:
hello.slice(5) // returns: 'world' hello.slice(5,-2) // returns: 'wor'
-
toUpperCase and toLowerCase - returns strings with all the characters converted to uppercase or lowercase, respectively:
const hello = 'Hello World'; hello.toUpperCase() // Returns: 'HELLO WORLD' hello.toLowerCase() // Returns: 'hello world'
-
replace - replaces a specified value with another value:
const hello = 'hello world'; hello.replace('world', 'internet') // Returns: 'hello internet'
-
trim - removes whitespace from both ends:
const hello = ' hello world '; hello.trim() // Returns: 'hello world'
-
split - splits a string into an array of substrings based on a specified separator:
const hello = 'hello world'; hello.split(' ') // Returns: ['hello', 'world']
-
padStart - pads the start of a string with a specified value until the resulting string reaches a specified length:
const hello = 'hello'; hello.padStart(10, '#') // Returns: '#####hello'
-
padEnd - pads the end of a string with a specified value until the resulting string reaches a specified length:
const hello = 'hello'; hello.padEnd(10, '#') // Returns: 'hello#####'
-
search - searches for a specified value and returns the position of the match:
const str = 'The quick brown fox jumps over the lazy dog'; str.search(/dog/i) // Returns: 40
Regular Expressions
Written between two forward slashes /pattern/
and can include flags such as i
for case-insensitive search. Often used in string methods such as match and search to search for patterns in strings.
/abc/
- matches the characters ‘abc’ in a string/[abc]/
- matches any character in the brackets (a, b, or c)/[^abc]/
- matches any character not in the brackets (not a, b, or c)/[0-9]/
- matches any digit (0-9)/[a-z]/
- matches any lowercase letter (a-z)/[A-Z]/
- matches any uppercase letter (A-Z)/./
- matches any character except newline/\\\\s/
- matches any whitespace character (space, tab, newline)/\\\\S/
- matches any non-whitespace character/^abc/
- matches ‘abc’ at the beginning of a string/abc$/
- matches ‘abc’ at the end of a string/a*b/
- matches zero or more occurrences of ‘a’ followed by ‘b’/a+b/
- matches one or more occurrences of ‘a’ followed by ‘b’/a?b/
- matches zero or one occurrence of ‘a’ followed by ‘b’/a{2}/
- matches exactly two occurrences of ‘a’/a{2,}/
- matches two or more occurrences of ‘a’/a{2,4}/
- matches between two and four occurrences of ‘a’
Boolean
Represent logical entities with only two possible values, true
or false
.
let isSunny = true
let isRaining = false
Conditional statements rely on boolean values to make decisions:
if (isSunny) {
console.log("It's a beautiful day!")
} else if (isRaining) {
console.log("Better bring an umbrella.")
} else {
console.log("I'm not sure what the weather is like.")
}
Comparison operators return boolean values:
let x = 5
let y = 10
let result = x < y // result is true
Truthy and Falsy
Some values are considered “truthy” and others are considered “falsy” when evaluated in a Boolean context.
Truthy values:
- non-empty string:
"hello"
- non-zero number:
42
- array (empty or not):
[]
or[1, 2, 3]
- object (empty or not):
{}
or{ key: 'value' }
Falsy values:
- empty string:
""
- the number zero: `0
null
undefined
NaN
(Not a Number)
Undefined
undefined
is a primitive value in JavaScript. A variable that has been declared but not assigned a value is of type undefined
.
let myVariable;
console.log(myVariable); // Output: undefined
When a function doesn’t explicitly return a value, it implicitly returns undefined.
function myFunction() {
}
console.log(myFunction()); // Output: undefined
Accessing a non-existent object property or array element returns undefined:
const obj = {};
console.log(obj.nonExistentProperty); // Output: undefined
const arr = [1, 2, 3];
console.log(arr[5]); // Output: undefined
Can be a source of errors if not handled properly:
let x = undefined;
console.log(x + 5); // Output: NaN
Null
A variable can be deliberately assigned a null
value - often used to indicate the absence of a value.
let myObject = null;
Should also be used with care:
let x = null;
console.log(x + 5); // Output: 5
Symbol
First introduced in ECMAScript 6 - a unique and immutable data type that represents an identifier. Used to define properties of an object that cannot be accessed or modified by other parts of the code.
Creating Symbols
Doesn’t require the new
keyword that objects do:
let mySymbol = Symbol();
A string can also be provided when creating a symbol - acts as a label for the symbol and can help with debugging.
let anotherSymbol = Symbol('test2');
Uniqueness
Unique even when providing a string when created:
Symbol('a') === Symbol('a') // returns: false
Use: Hide Information
let mySymbol = Symbol('answer');
let obj = {
x: 24,
[mySymbol]: 42
}
console.log(obj.x); // Output: 24
console.log(obj.mySymbol); // Output: undefined
console.log(obj[mySymbol]); // Output: 42
mySymbol.toString() // Output: "Symbol(answer)"
NB: The
mySymbol
variable must be kept around in order to access theobj
property.
let obj = {
x: 24,
[Symbol("answer")]: 42
}
console.log(obj[Symbol("answer")]); // Output: undefined
Use: Private methods
Can be used to create complex internal logic that can’t be accessed from outside the object:
const obj = {
[Symbol.for('sum')]: function(x, y) {
return x + y;
},
add: function(x, y) {
return this[Symbol.for('sum')](x, y);
}
};
console.log(obj.add(2, 3)); // Output: 5
console.log(obj.sum(2, 3)); // TypeError: obj.sum is not a function
Symbol.for
is used to retrieve a symbol from the “global symbol registry”.
Global Symbol Registry
More of a “concept” (not how actually implemented by JS engines) but useful for the understanding how Symbol.for
and Symbol.keyFor
are used to retrieve symbols and keys across different files or global scopes.
Symbol('sum') === Symbol('sum') // returns: false
Symbol.for('sum') === Symbol.for('sum') // returns: true
Symbol.keyFor(Symbol.for("sum")) === "sum" // returns: true
Danger: No String Conversation
No direct string conversion for symbols:
let mySymbol = Symbol('answer');
console.log(mySymbol); // Outputs: undefined
BigInt
A numeric data type introduced in ES2020, used to represent integers that are larger than the range of the standard Number
data type. They are created by appending the letter “n” to the end of an integer literal or by using the BigInt()
constructor:
const bigNumber = 1234567890123456789012345678901234567890n;
const anotherBig = BigInt('1234567890123456789012345678901234567890')
BigInt values can only be used in mathematical operations with other BigInt values:
const bigNumber = 1234567890123456789012345678901234567890n;
const anotherBig = BigInt('1234567890123456789012345678901234567890')
console.log(bigNumber + anotherBig); // 2469135780246913578024691357802469135780n
console.log(bigNumber + 5);
// Uncaught TypeError: Cannot mix BigInt and other types, use explicit conversions
BigInt Methods
-
toString - converts a BigInt to a string:
const bigNumber = 1234567890123456789012345678901234567890n; console.log(bigNumber.toString()); // Output: "1234567890123456789012345678901234567890"
-
valueOf - returns the primitive value of a BigInt:
const bigNumber = 1234567890123456789012345678901234567890n; console.log(bigNumber.valueOf()); // Output: 1234567890123456789012345678901234567890
-
toExponential - returns a string representing the number in exponential notation:
const bigNumber = 1234567890123456789012345678901234567890n; console.log(bigNumber.toExponential()); // Output: "1.23456789012345678901234567890123456789e+39"
-
toFixed - returns a string representing the number in fixed-point notation:
const bigNumber = 1234567890123456789012345678901234567890n; console.log(bigNumber.toFixed(2)); // Output: "1234567890123456789012345678901234567890.00"
-
toPrecision - returns a string representing the number to a specified precision:
const bigNumber = 1234567890123456789012345678901234567890n; console.log(bigNumber.toPrecision(5)); // Output: "1.2346e+39"
Type Coercion
The process of converting a value from one type to another. As a loosely typed language, by default, JS will automatically convert data types when needed. Can lead to unexpected behavior.
Implicit Coercion
When two values of different types are used:
let x = 10 + "5";
console.log(x); // Output: 105
Implicit Coercion rules:
Number
+String
=String
Number
+Boolean
=Number
String
+Boolean
=String
Number
+Null
=Number
Number
+Undefined
=NaN
String
+Null
=String
String
+Undefined
=String
Boolean
+Null
=Number
Boolean
+Undefined
=NaN
Null
+Undefined
=NaN
Explicit Coercion
To avoid unexpected behavior, you can explicitly convert a value from one type to another using the following methods:
let x = 10 + "5".toInteger();
console.log(x); // Output: 15
Explicit coercion methods:
Number()
parseInt()
parseFloat()
toInteger()
toFixed()
toPrecision()
toExponential()
String()
toString()
toUTCString()
toDateString()
toTimeString()
toLocaleString()
toLocaleDateString()
toLocaleTimeString()
Boolean()