Skip to content

Data Types

JavaScript has a rich type system that includes both primitive and reference types. Understanding data types and their behaviors is fundamental to writing effective JavaScript code.

// Different ways to create arrays
const arr1 = [1, 2, 3, 4, 5];
const arr2 = new Array(5); // [undefined × 5]
const arr3 = new Array(1, 2, 3); // [1, 2, 3]
const arr4 = Array.from('hello'); // ['h', 'e', 'l', 'l', 'o']
const arr5 = Array.of(1, 2, 3); // [1, 2, 3]
// Array.from with mapping function
const numbers = Array.from({ length: 5 }, (_, i) => i * 2); // [0, 2, 4, 6, 8]
const range = Array.from({ length: 10 }, (_, i) => i + 1); // [1, 2, 3, ..., 10]
// Sparse arrays
const sparse = [1, , , 4]; // [1, undefined × 2, 4]
console.log(sparse.length); // 4
console.log(1 in sparse); // false
console.log(3 in sparse); // true
// Array-like objects
const arrayLike = { 0: 'a', 1: 'b', 2: 'c', length: 3 };
const realArray = Array.from(arrayLike); // ['a', 'b', 'c']
const fruits = ['apple', 'banana', 'orange'];
// Adding elements
fruits.push('grape'); // Returns new length: 4
fruits.unshift('mango'); // Returns new length: 5
fruits.splice(2, 0, 'kiwi'); // Insert at index 2
console.log(fruits); // ['mango', 'apple', 'kiwi', 'banana', 'orange', 'grape']
// Removing elements
const lastFruit = fruits.pop(); // 'grape'
const firstFruit = fruits.shift(); // 'mango'
const removed = fruits.splice(1, 2); // Remove 2 elements starting at index 1
console.log(fruits); // ['apple', 'orange']
console.log(removed); // ['kiwi', 'banana']
// Sorting and reversing
const numbers = [3, 1, 4, 1, 5, 9, 2, 6];
numbers.sort(); // [1, 1, 2, 3, 4, 5, 6, 9]
numbers.reverse(); // [9, 6, 5, 4, 3, 2, 1, 1]
// Custom sorting
const people = [
{ name: 'Alice', age: 30 },
{ name: 'Bob', age: 25 },
{ name: 'Charlie', age: 35 }
];
people.sort((a, b) => a.age - b.age); // Sort by age ascending
people.sort((a, b) => b.name.localeCompare(a.name)); // Sort by name descending
// Fill method
const zeros = new Array(5).fill(0); // [0, 0, 0, 0, 0]
const matrix = Array(3).fill(null).map(() => Array(3).fill(0));
const original = [1, 2, 3, 4, 5];
// Concatenation
const combined = original.concat([6, 7, 8]); // [1, 2, 3, 4, 5, 6, 7, 8]
const spread = [...original, 6, 7, 8]; // Same result with spread
// Slicing
const subset = original.slice(1, 4); // [2, 3, 4]
const copy = original.slice(); // [1, 2, 3, 4, 5] (shallow copy)
// Joining
const joined = original.join(', '); // '1, 2, 3, 4, 5'
const noSeparator = original.join(''); // '12345'
// Searching
const index = original.indexOf(3); // 2
const lastIndex = original.lastIndexOf(3); // 2
const includes = original.includes(3); // true
// Finding
const found = original.find(x => x > 3); // 4
const foundIndex = original.findIndex(x => x > 3); // 3
const foundLast = original.findLast(x => x > 3); // 5 (ES2023)
const foundLastIndex = original.findLastIndex(x => x > 3); // 4 (ES2023)
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// Map - transform each element
const doubled = numbers.map(x => x * 2); // [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
const squared = numbers.map(x => x ** 2); // [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
// Filter - select elements based on condition
const evens = numbers.filter(x => x % 2 === 0); // [2, 4, 6, 8, 10]
const greaterThanFive = numbers.filter(x => x > 5); // [6, 7, 8, 9, 10]
// Reduce - accumulate values
const sum = numbers.reduce((acc, curr) => acc + curr, 0); // 55
const product = numbers.reduce((acc, curr) => acc * curr, 1); // 3628800
const max = numbers.reduce((acc, curr) => Math.max(acc, curr)); // 10
// Complex reduce examples
const people = [
{ name: 'Alice', age: 30, department: 'Engineering' },
{ name: 'Bob', age: 25, department: 'Marketing' },
{ name: 'Charlie', age: 35, department: 'Engineering' },
{ name: 'Diana', age: 28, department: 'Marketing' }
];
// Group by department
const byDepartment = people.reduce((acc, person) => {
if (!acc[person.department]) {
acc[person.department] = [];
}
acc[person.department].push(person);
return acc;
}, {});
// Calculate average age
const averageAge = people.reduce((sum, person, index, array) => {
sum += person.age;
return index === array.length - 1 ? sum / array.length : sum;
}, 0);
// ReduceRight - process from right to left
const rightToLeft = [1, 2, 3, 4].reduceRight((acc, curr) => acc + curr); // 10
// Some and every
const hasEven = numbers.some(x => x % 2 === 0); // true
const allPositive = numbers.every(x => x > 0); // true
const allEven = numbers.every(x => x % 2 === 0); // false
// ForEach - side effects
numbers.forEach((value, index, array) => {
console.log(`Index ${index}: ${value}`);
});
// Chaining methods
const result = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
.filter(x => x % 2 === 0) // [2, 4, 6, 8, 10]
.map(x => x * x) // [4, 16, 36, 64, 100]
.reduce((sum, x) => sum + x, 0); // 220
// Flattening arrays
const nested = [[1, 2], [3, 4], [5, 6]];
const flattened1 = nested.flat(); // [1, 2, 3, 4, 5, 6]
const deepNested = [1, [2, [3, [4, 5]]]];
const flattened2 = deepNested.flat(3); // [1, 2, 3, 4, 5]
const completelyFlat = deepNested.flat(Infinity); // [1, 2, 3, 4, 5]
// FlatMap - map then flatten
const words = ['hello', 'world'];
const letters = words.flatMap(word => word.split('')); // ['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd']
// Array deduplication
const duplicates = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4];
const unique = [...new Set(duplicates)]; // [1, 2, 3, 4]
// Complex deduplication by property
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 1, name: 'Alice' },
{ id: 3, name: 'Charlie' }
];
const uniqueUsers = users.filter((user, index, array) =>
array.findIndex(u => u.id === user.id) === index
);
// Intersection and difference
const arr1 = [1, 2, 3, 4, 5];
const arr2 = [3, 4, 5, 6, 7];
const intersection = arr1.filter(x => arr2.includes(x)); // [3, 4, 5]
const difference = arr1.filter(x => !arr2.includes(x)); // [1, 2]
const symmetricDiff = [...difference, ...arr2.filter(x => !arr1.includes(x))]; // [1, 2, 6, 7]
// Array chunking
function chunk(array, size) {
const chunks = [];
for (let i = 0; i < array.length; i += size) {
chunks.push(array.slice(i, i + size));
}
return chunks;
}
const chunked = chunk([1, 2, 3, 4, 5, 6, 7, 8], 3); // [[1, 2, 3], [4, 5, 6], [7, 8]]
// Array rotation
function rotateLeft(array, positions) {
const n = positions % array.length;
return [...array.slice(n), ...array.slice(0, n)];
}
function rotateRight(array, positions) {
const n = positions % array.length;
return [...array.slice(-n), ...array.slice(0, -n)];
}
const original = [1, 2, 3, 4, 5];
const leftRotated = rotateLeft(original, 2); // [3, 4, 5, 1, 2]
const rightRotated = rotateRight(original, 2); // [4, 5, 1, 2, 3]
// Different ways to create objects
const obj1 = {}; // Object literal
const obj2 = new Object(); // Constructor
const obj3 = Object.create(null); // No prototype
const obj4 = Object.create(Object.prototype); // Explicit prototype
// Property definition
const person = {
firstName: 'John',
lastName: 'Doe',
age: 30,
'full-name': 'John Doe', // Property with special characters
42: 'meaning of life' // Numeric property
};
// Property access
console.log(person.firstName); // 'John'
console.log(person['lastName']); // 'Doe'
console.log(person['full-name']); // 'John Doe'
console.log(person[42]); // 'meaning of life'
// Dynamic property access
const propName = 'age';
console.log(person[propName]); // 30
// Property existence checking
console.log('firstName' in person); // true
console.log(person.hasOwnProperty('firstName')); // true
console.log(person.nonExistent !== undefined); // false
const source1 = { a: 1, b: 2 };
const source2 = { b: 3, c: 4 };
const target = { x: 10 };
// Object.assign - shallow copy/merge
const merged = Object.assign(target, source1, source2);
console.log(merged); // { x: 10, a: 1, b: 3, c: 4 }
// Spread operator - alternative to Object.assign
const spreadMerged = { ...target, ...source1, ...source2 };
// Object.keys, values, entries
const data = { name: 'Alice', age: 30, city: 'New York' };
const keys = Object.keys(data); // ['name', 'age', 'city']
const values = Object.values(data); // ['Alice', 30, 'New York']
const entries = Object.entries(data); // [['name', 'Alice'], ['age', 30], ['city', 'New York']]
// Object.fromEntries - reverse of Object.entries
const reconstructed = Object.fromEntries(entries); // { name: 'Alice', age: 30, city: 'New York' }
// Transform object with entries
const doubled = Object.fromEntries(
Object.entries({ a: 1, b: 2, c: 3 }).map(([key, value]) => [key, value * 2])
); // { a: 2, b: 4, c: 6 }
// Object.freeze, seal, preventExtensions
const obj = { a: 1, b: 2 };
Object.freeze(obj); // No modifications allowed
Object.seal(obj); // No property addition/deletion, but modification allowed
Object.preventExtensions(obj); // No property addition, but deletion and modification allowed
console.log(Object.isFrozen(obj)); // true
console.log(Object.isSealed(obj)); // true
console.log(Object.isExtensible(obj)); // false
// Property descriptors
const obj = {};
Object.defineProperty(obj, 'readOnly', {
value: 'cannot change',
writable: false,
enumerable: true,
configurable: false
});
Object.defineProperty(obj, 'hidden', {
value: 'secret',
writable: true,
enumerable: false, // Won't show in Object.keys()
configurable: true
});
// Getter and setter properties
const user = {
_firstName: '',
_lastName: '',
get fullName() {
return `${this._firstName} ${this._lastName}`.trim();
},
set fullName(value) {
[this._firstName, this._lastName] = value.split(' ');
},
get firstName() { return this._firstName; },
set firstName(value) { this._firstName = value; },
get lastName() { return this._lastName; },
set lastName(value) { this._lastName = value; }
};
user.fullName = 'John Doe';
console.log(user.firstName); // 'John'
console.log(user.lastName); // 'Doe'
// Object destructuring with defaults and renaming
const config = {
host: 'localhost',
port: 3000,
ssl: false
};
const {
host,
port = 8080, // Default value
ssl: useSSL, // Rename
database = 'mydb' // Default for missing property
} = config;
// Nested destructuring
const user = {
name: 'Alice',
address: {
street: '123 Main St',
city: 'Boston',
country: 'USA'
}
};
const {
name,
address: { city, country }
} = user;
// Rest in destructuring
const { name, ...rest } = { name: 'Alice', age: 30, city: 'Boston' };
console.log(rest); // { age: 30, city: 'Boston' }
// Object cloning
function shallowClone(obj) {
return { ...obj };
}
function deepClone(obj) {
if (obj === null || typeof obj !== 'object') return obj;
if (obj instanceof Date) return new Date(obj.getTime());
if (obj instanceof Array) return obj.map(deepClone);
if (obj instanceof Object) {
const cloned = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
cloned[key] = deepClone(obj[key]);
}
}
return cloned;
}
}
// Modern deep cloning (where supported)
const original = { a: 1, b: { c: 2 }, d: new Date() };
const cloned = structuredClone(original);
// Object comparison
function deepEqual(a, b) {
if (a === b) return true;
if (a == null || b == null) return false;
if (typeof a !== typeof b) return false;
if (typeof a === 'object') {
const keysA = Object.keys(a);
const keysB = Object.keys(b);
if (keysA.length !== keysB.length) return false;
for (const key of keysA) {
if (!keysB.includes(key)) return false;
if (!deepEqual(a[key], b[key])) return false;
}
return true;
}
return false;
}
// Set creation and basic operations
const set1 = new Set([1, 2, 3, 4, 5]);
const set2 = new Set('hello'); // Set { 'h', 'e', 'l', 'o' }
// Adding and removing elements
set1.add(6);
set1.add(6); // Duplicates are ignored
set1.delete(1);
console.log(set1.has(2)); // true
console.log(set1.size); // 5
// Set iteration
for (const value of set1) {
console.log(value);
}
set1.forEach(value => console.log(value));
// Convert to array
const arrayFromSet = [...set1];
const arrayFromSet2 = Array.from(set1);
// Set operations
function setUnion(setA, setB) {
return new Set([...setA, ...setB]);
}
function setIntersection(setA, setB) {
return new Set([...setA].filter(x => setB.has(x)));
}
function setDifference(setA, setB) {
return new Set([...setA].filter(x => !setB.has(x)));
}
function setSymmetricDifference(setA, setB) {
return new Set([
...[...setA].filter(x => !setB.has(x)),
...[...setB].filter(x => !setA.has(x))
]);
}
const setA = new Set([1, 2, 3, 4]);
const setB = new Set([3, 4, 5, 6]);
console.log(setUnion(setA, setB)); // Set { 1, 2, 3, 4, 5, 6 }
console.log(setIntersection(setA, setB)); // Set { 3, 4 }
console.log(setDifference(setA, setB)); // Set { 1, 2 }
console.log(setSymmetricDifference(setA, setB)); // Set { 1, 2, 5, 6 }
// Practical Set usage
function removeDuplicates(array) {
return [...new Set(array)];
}
function hasUniqueElements(array) {
return array.length === new Set(array).size;
}
function findCommonElements(arrays) {
if (arrays.length === 0) return [];
const sets = arrays.map(arr => new Set(arr));
const firstSet = sets[0];
return [...firstSet].filter(item =>
sets.every(set => set.has(item))
);
}
// Map creation and basic operations
const map1 = new Map();
const map2 = new Map([
['key1', 'value1'],
['key2', 'value2'],
[1, 'number key'],
[true, 'boolean key']
]);
// Adding and retrieving values
map1.set('name', 'Alice');
map1.set('age', 30);
map1.set('city', 'New York');
console.log(map1.get('name')); // 'Alice'
console.log(map1.has('age')); // true
console.log(map1.size); // 3
// Object as key (unique feature of Map)
const objKey = { id: 1 };
map1.set(objKey, 'object value');
console.log(map1.get(objKey)); // 'object value'
// Map iteration
for (const [key, value] of map1) {
console.log(`${key}: ${value}`);
}
for (const key of map1.keys()) {
console.log(key);
}
for (const value of map1.values()) {
console.log(value);
}
map1.forEach((value, key) => {
console.log(`${key} => ${value}`);
});
// Convert between Map and Object
function mapToObject(map) {
const obj = {};
for (const [key, value] of map) {
obj[key] = value;
}
return obj;
}
function objectToMap(obj) {
return new Map(Object.entries(obj));
}
// Practical Map usage
class Cache {
constructor(maxSize = 100) {
this.cache = new Map();
this.maxSize = maxSize;
}
get(key) {
if (this.cache.has(key)) {
// Move to end (LRU behavior)
const value = this.cache.get(key);
this.cache.delete(key);
this.cache.set(key, value);
return value;
}
return undefined;
}
set(key, value) {
if (this.cache.has(key)) {
this.cache.delete(key);
} else if (this.cache.size >= this.maxSize) {
// Remove oldest entry
const firstKey = this.cache.keys().next().value;
this.cache.delete(firstKey);
}
this.cache.set(key, value);
}
has(key) {
return this.cache.has(key);
}
clear() {
this.cache.clear();
}
size() {
return this.cache.size;
}
}
// Frequency counter with Map
function countFrequency(items) {
const frequency = new Map();
for (const item of items) {
frequency.set(item, (frequency.get(item) || 0) + 1);
}
return frequency;
}
const words = ['apple', 'banana', 'apple', 'cherry', 'banana', 'apple'];
const freq = countFrequency(words);
console.log(freq); // Map { 'apple' => 3, 'banana' => 2, 'cherry' => 1 }
// Group by with Map
function groupBy(items, keyFn) {
const groups = new Map();
for (const item of items) {
const key = keyFn(item);
if (!groups.has(key)) {
groups.set(key, []);
}
groups.get(key).push(item);
}
return groups;
}
const people = [
{ name: 'Alice', age: 25, department: 'Engineering' },
{ name: 'Bob', age: 30, department: 'Marketing' },
{ name: 'Charlie', age: 25, department: 'Engineering' }
];
const byDepartment = groupBy(people, person => person.department);
const byAge = groupBy(people, person => person.age);
// Private data with WeakMap
const privateData = new WeakMap();
class User {
constructor(name, email) {
privateData.set(this, {
name,
email,
created: new Date()
});
}
getName() {
return privateData.get(this).name;
}
setName(name) {
privateData.get(this).name = name;
}
getEmail() {
return privateData.get(this).email;
}
toString() {
const data = privateData.get(this);
return `User: ${data.name} (${data.email})`;
}
}
// Metadata association
const elementMetadata = new WeakMap();
function addMetadata(element, metadata) {
elementMetadata.set(element, metadata);
}
function getMetadata(element) {
return elementMetadata.get(element);
}
// DOM elements with metadata
const button = document.createElement('button');
addMetadata(button, {
clicked: 0,
created: new Date(),
type: 'primary'
});
button.addEventListener('click', () => {
const meta = getMetadata(button);
meta.clicked++;
console.log(`Button clicked ${meta.clicked} times`);
});
// Caching with automatic cleanup
const computeCache = new WeakMap();
function expensiveComputation(obj) {
if (computeCache.has(obj)) {
console.log('Cache hit');
return computeCache.get(obj);
}
console.log('Computing...');
const result = performExpensiveOperation(obj);
computeCache.set(obj, result);
return result;
}
function performExpensiveOperation(obj) {
// Simulate expensive computation
return Object.keys(obj).length * Math.random();
}
// Object tracking
const processedObjects = new WeakSet();
function processObject(obj) {
if (processedObjects.has(obj)) {
console.log('Object already processed');
return;
}
// Process the object
console.log('Processing object...');
// Mark as processed
processedObjects.add(obj);
}
// Preventing circular references in serialization
const serializing = new WeakSet();
function customStringify(obj) {
if (serializing.has(obj)) {
return '"[Circular Reference]"';
}
if (typeof obj === 'object' && obj !== null) {
serializing.add(obj);
try {
if (Array.isArray(obj)) {
const items = obj.map(item => customStringify(item));
return `[${items.join(',')}]`;
} else {
const props = Object.keys(obj).map(key =>
`"${key}":${customStringify(obj[key])}`
);
return `{${props.join(',')}}`;
}
} finally {
serializing.delete(obj);
}
}
return JSON.stringify(obj);
}
// Test circular reference
const circularObj = { name: 'test' };
circularObj.self = circularObj;
console.log(customStringify(circularObj)); // {"name":"test","self":"[Circular Reference]"}
// Access control
const authorizedObjects = new WeakSet();
function authorize(obj) {
authorizedObjects.add(obj);
}
function isAuthorized(obj) {
return authorizedObjects.has(obj);
}
function secureOperation(obj) {
if (!isAuthorized(obj)) {
throw new Error('Access denied');
}
// Perform secure operation
console.log('Secure operation performed');
}

This comprehensive guide to JavaScript data types and structures provides the foundation for effective data manipulation and organization in JavaScript applications.


Master these data structures to efficiently organize and manipulate data in your JavaScript applications.