1. JavaScript
  2. Fundamentals
  3. Primitive Data Types

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.

  1. Number - numeric values, including integers and floating-point numbers.

     let answer = 42;
     let pi = 3.14;
    
  2. String - textual data, enclosed in single quotes (‘’) or double quotes (“”).

     let name = "Paul";
     let message = 'Hello, World!';
    
  3. Boolean - a logical value, either true or false.

     let isOpen = true;
     let isClosed = false;
    
  4. Undefined - a variable that has been declared but not assigned a value.

     let myVariable;
    
  5. Null - a deliberate null value (represents the absence of a value).

       let myObject = null;
    
  6. Symbol (introduced in ECMAScript 2015) - a unique identifier.

     let mySymbol = Symbol("mySymbol");
    
  7. 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 number
  • parseInt() - 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 the obj 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()