JavaScript Arrays and Array Methods
1. Array Creation and Initialization Patterns
| Pattern | Syntax | Description | Example |
|---|---|---|---|
| Array Literal | [el1, el2, ...] |
Most common creation method; supports mixed types and sparse arrays | const arr = [1, 2, 3]; |
| Array Constructor | new Array(length) |
Creates array with specified length (holes); avoid for single numeric argument | new Array(3) // [empty × 3] |
| Array.of() | Array.of(...items) |
Creates array from arguments; fixes Array() single-number issue | Array.of(3) // [3] |
| Array.from() | Array.from(iterable, mapFn) |
Creates array from iterable/array-like; optional mapper function | Array.from('abc') // ['a','b','c'] |
| Spread Syntax | [...iterable] |
Shallow copy or convert iterable to array; modern and concise | [...set] // array from Set |
| Array.fill() | Array(n).fill(value) |
Create pre-filled array; value is shared reference for objects | Array(3).fill(0) // [0,0,0] |
| Array.keys() | Array.from(Array(n).keys()) |
Generate sequential number array from 0 to n-1 | [...Array(3).keys()] // [0,1,2] |
Example: Various array creation patterns
// Literal - most common
const fruits = ['apple', 'banana', 'orange'];
// Array.of - safe with single number
const single = Array.of(5); // [5] not [empty × 5]
// Array.from with mapper
const squares = Array.from({length: 5}, (_, i) => i ** 2);
// [0, 1, 4, 9, 16]
// From string
const chars = Array.from('hello'); // ['h','e','l','l','o']
// From Set
const unique = [...new Set([1, 2, 2, 3])]; // [1, 2, 3]
// Pre-fill with value
const zeros = Array(10).fill(0);
// Sequential numbers
const range = [...Array(5).keys()]; // [0, 1, 2, 3, 4]
const rangeFrom1 = Array.from({length: 5}, (_, i) => i + 1);
// [1, 2, 3, 4, 5]
// 2D array (careful with fill!)
const matrix = Array(3).fill(null).map(() => Array(3).fill(0));
Note: Avoid
new Array(n).fill([]) for 2D arrays as all rows share same reference.
Use .map(() => []) instead.
2. Array Mutating Methods (push, pop, shift, unshift, splice, sort, reverse)
| Method | Syntax | Description | Returns |
|---|---|---|---|
| push() | arr.push(el1, ...) |
Adds elements to end; modifies original array; O(1) time | New length |
| pop() | arr.pop() |
Removes and returns last element; O(1) time | Removed element |
| unshift() | arr.unshift(el1, ...) |
Adds elements to beginning; shifts indices; O(n) time | New length |
| shift() | arr.shift() |
Removes and returns first element; shifts indices; O(n) time | Removed element |
| splice() | arr.splice(start, deleteCount, ...items) |
Add/remove elements at any position; powerful but complex | Array of deleted elements |
| sort() | arr.sort(compareFn) |
Sorts in-place; default: string comparison; provide compareFn for numbers | Sorted array (same reference) |
| reverse() | arr.reverse() |
Reverses array in-place; O(n) time | Reversed array (same reference) |
| fill() | arr.fill(value, start, end) |
Fills with static value; optional range; O(n) time | Modified array |
| copyWithin() | arr.copyWithin(target, start, end) |
Shallow copies part of array to another location in same array | Modified array |
Example: Mutating array methods
const arr = [1, 2, 3];
// Stack operations (end)
arr.push(4, 5); // [1,2,3,4,5] returns 5
arr.pop(); // [1,2,3,4] returns 5
// Queue operations (beginning)
arr.unshift(0); // [0,1,2,3,4] returns 5
arr.shift(); // [1,2,3,4] returns 0
// splice - remove
const items = [1, 2, 3, 4, 5];
items.splice(2, 2); // [1,2,5] returns [3,4]
// splice - insert
items.splice(1, 0, 'a', 'b'); // [1,'a','b',2,5]
// splice - replace
items.splice(0, 2, 'x'); // ['x','b',2,5]
// sort - numbers (must provide compareFn!)
const nums = [10, 2, 5, 1];
nums.sort(); // [1, 10, 2, 5] ❌ string sort!
nums.sort((a, b) => a - b); // [1, 2, 5, 10] ✓
// sort - objects
const users = [{age: 30}, {age: 20}, {age: 25}];
users.sort((a, b) => a.age - b.age);
// reverse
[1, 2, 3].reverse(); // [3, 2, 1]
// fill
Array(5).fill(0); // [0,0,0,0,0]
[1,2,3,4,5].fill(0, 2, 4); // [1,2,0,0,5]
// copyWithin
[1,2,3,4,5].copyWithin(0, 3); // [4,5,3,4,5]
Warning: Default
sort() converts to strings! Always provide compare function for
numbers: arr.sort((a,b) => a - b)
3. Array Non-mutating Methods (slice, concat, join)
| Method | Syntax | Description | Returns |
|---|---|---|---|
| slice() | arr.slice(start, end) |
Shallow copy of portion; negative indices from end; doesn't modify original | New array |
| concat() | arr.concat(arr2, ...) |
Merges arrays/values; shallow copy; doesn't modify originals | New array |
| join() | arr.join(separator) |
Converts to string with separator; default comma; doesn't modify | String |
| toString() | arr.toString() |
Converts to comma-separated string; same as join(',') |
String |
| toLocaleString() | arr.toLocaleString() |
Locale-aware string conversion; respects number/date formatting | String |
| flat() ES2019 | arr.flat(depth) |
Flattens nested arrays; default depth 1; Infinity for full flatten | New flattened array |
| flatMap() ES2019 | arr.flatMap(fn) |
Maps then flattens (depth 1); more efficient than map().flat() | New array |
| with() ES2023 | arr.with(index, value) |
Returns new array with element replaced; immutable alternative to arr[i]=val | New array |
| toReversed() ES2023 | arr.toReversed() |
Non-mutating reverse; returns new reversed array | New reversed array |
| toSorted() ES2023 | arr.toSorted(compareFn) |
Non-mutating sort; returns new sorted array | New sorted array |
| toSpliced() ES2023 | arr.toSpliced(start, deleteCount, ...items) |
Non-mutating splice; returns new array with changes | New array |
Example: Non-mutating array methods
const arr = [1, 2, 3, 4, 5];
// slice - extract portion
arr.slice(1, 3); // [2, 3]
arr.slice(-2); // [4, 5] (last 2)
arr.slice(); // [1,2,3,4,5] (shallow copy)
// concat - merge
[1, 2].concat([3, 4]); // [1, 2, 3, 4]
[1].concat(2, [3, 4], 5); // [1, 2, 3, 4, 5]
// join - to string
['a', 'b', 'c'].join(); // "a,b,c"
['a', 'b', 'c'].join(''); // "abc"
['a', 'b', 'c'].join(' - '); // "a - b - c"
// flat - nested arrays
[1, [2, 3], [4, [5]]].flat(); // [1, 2, 3, 4, [5]]
[1, [2, [3, [4]]]].flat(2); // [1, 2, 3, [4]]
[1, [2, [3, [4]]]].flat(Infinity); // [1, 2, 3, 4]
// flatMap - map then flatten
['hello', 'world'].flatMap(s => s.split(''));
// ['h','e','l','l','o','w','o','r','l','d']
[1, 2, 3].flatMap(x => [x, x * 2]);
// [1, 2, 2, 4, 3, 6]
// ES2023 immutable methods
const original = [3, 1, 2];
original.toSorted(); // [1, 2, 3]
console.log(original); // [3, 1, 2] unchanged
original.toReversed(); // [2, 1, 3]
original.with(1, 99); // [3, 99, 2]
original.toSpliced(1, 1, 'a', 'b'); // [3, 'a', 'b', 2]
Note: Use spread
[...arr] or slice() for shallow copy. ES2023 adds
toSorted(), toReversed(), toSpliced(), with() for immutable
operations.
4. Array Iteration Methods (forEach, map, filter, reduce, reduceRight)
| Method | Syntax | Description | Returns |
|---|---|---|---|
| forEach() | arr.forEach((el, i, arr) => {}) |
Execute function for each element; no return value; can't break/continue | undefined |
| map() | arr.map((el, i, arr) => {}) |
Transform each element; returns new array with results | New array |
| filter() | arr.filter((el, i, arr) => {}) |
Keep elements that pass test; returns new array with matches | New array |
| reduce() | arr.reduce((acc, el, i, arr) => {}, init) |
Reduce to single value; accumulator pattern; init value recommended | Any value |
| reduceRight() | arr.reduceRight((acc, el) => {}, init) |
Like reduce but right-to-left; useful for right-associative operations | Any value |
| flatMap() | arr.flatMap((el, i, arr) => {}) |
Map then flatten depth 1; efficient for map + flat combination | New flattened array |
| entries() | arr.entries() |
Returns iterator of [index, value] pairs | Iterator |
| keys() | arr.keys() |
Returns iterator of indices | Iterator |
| values() | arr.values() |
Returns iterator of values | Iterator |
Example: Array iteration methods
const nums = [1, 2, 3, 4, 5];
// forEach - side effects only
nums.forEach((n, i) => console.log(`${i}: ${n}`));
// map - transform
const doubled = nums.map(n => n * 2); // [2,4,6,8,10]
const objects = nums.map(n => ({value: n}));
// filter - select
const evens = nums.filter(n => n % 2 === 0); // [2,4]
const large = nums.filter(n => n > 3); // [4,5]
// reduce - accumulate
const sum = nums.reduce((acc, n) => acc + n, 0); // 15
const product = nums.reduce((acc, n) => acc * n, 1); // 120
// reduce - group by
const items = ['a', 'b', 'c', 'a', 'b'];
const counts = items.reduce((acc, item) => {
acc[item] = (acc[item] || 0) + 1;
return acc;
}, {}); // {a: 2, b: 2, c: 1}
// reduce - flatten
[[1, 2], [3, 4], [5]].reduce((acc, arr) => acc.concat(arr), []);
// [1, 2, 3, 4, 5] (use flat() instead!)
// Method chaining
nums
.filter(n => n % 2 === 0)
.map(n => n * 2)
.reduce((acc, n) => acc + n, 0); // 12
// flatMap - map and flatten
['hello', 'world'].flatMap(w => w.split(''));
// ['h','e','l','l','o','w','o','r','l','d']
// Iterators
for (const [i, val] of nums.entries()) {
console.log(i, val); // 0 1, 1 2, ...
}
for (const i of nums.keys()) {
console.log(i); // 0, 1, 2, 3, 4
}
Note: Always provide initial value to
reduce() to avoid errors on empty arrays.
Use for...of if you need to break/continue; forEach() can't be stopped early.
5. Array Search Methods (find, findIndex, includes, indexOf, lastIndexOf)
| Method | Syntax | Description | Returns |
|---|---|---|---|
| find() | arr.find((el, i, arr) => {}) |
Returns first element that passes test; stops on first match | Element or undefined |
| findLast() ES2023 | arr.findLast((el, i, arr) => {}) |
Like find() but searches right-to-left; returns last match | Element or undefined |
| findIndex() | arr.findIndex((el, i, arr) => {}) |
Returns index of first element that passes test | Index or -1 |
| findLastIndex() ES2023 | arr.findLastIndex((el, i, arr) => {}) |
Like findIndex() but searches right-to-left | Index or -1 |
| includes() | arr.includes(value, fromIndex) |
Checks if array contains value; uses SameValueZero (handles NaN) | Boolean |
| indexOf() | arr.indexOf(value, fromIndex) |
Returns first index of value; uses strict equality (===); -1 if not found | Index or -1 |
| lastIndexOf() | arr.lastIndexOf(value, fromIndex) |
Returns last index of value; searches backwards | Index or -1 |
| at() ES2022 | arr.at(index) |
Returns element at index; negative indices from end; undefined if out of bounds | Element or undefined |
Example: Array search methods
const users = [
{id: 1, name: 'Alice', age: 25},
{id: 2, name: 'Bob', age: 30},
{id: 3, name: 'Charlie', age: 25}
];
// find - first match
const bob = users.find(u => u.name === 'Bob');
// {id: 2, name: 'Bob', age: 30}
const young = users.find(u => u.age < 30);
// {id: 1, name: 'Alice', age: 25}
// findLast - last match
const lastYoung = users.findLast(u => u.age === 25);
// {id: 3, name: 'Charlie', age: 25}
// findIndex
const bobIndex = users.findIndex(u => u.name === 'Bob'); // 1
const notFound = users.findIndex(u => u.name === 'Dave'); // -1
// includes - value check
[1, 2, 3].includes(2); // true
[1, 2, 3].includes(4); // false
[1, 2, NaN].includes(NaN); // true ✓ (indexOf fails here)
// indexOf - strict equality
['a', 'b', 'c'].indexOf('b'); // 1
['a', 'b', 'c'].indexOf('d'); // -1
[1, 2, 3, 2].indexOf(2); // 1 (first occurrence)
// lastIndexOf - search backwards
[1, 2, 3, 2, 1].lastIndexOf(2); // 3
[1, 2, 3].lastIndexOf(4); // -1
// at - negative indexing
const arr = ['a', 'b', 'c', 'd'];
arr.at(0); // 'a'
arr.at(-1); // 'd' (last)
arr.at(-2); // 'c' (second to last)
arr.at(10); // undefined
// Comparison: includes vs indexOf
[1, 2, NaN].includes(NaN); // true
[1, 2, NaN].indexOf(NaN); // -1 ❌
// Check existence
if (users.find(u => u.id === 2)) {
// Found
}
// Get index and value
const index = users.findIndex(u => u.age === 25);
if (index !== -1) {
const user = users[index];
}
Note: Use
includes() for existence check (handles NaN); find() for
objects with conditions; at() for negative indexing (cleaner than
arr[arr.length - 1]).
6. Array Testing Methods (every, some)
| Method | Syntax | Description | Returns |
|---|---|---|---|
| every() | arr.every((el, i, arr) => {}) |
Tests if ALL elements pass test; short-circuits on first false | Boolean |
| some() | arr.some((el, i, arr) => {}) |
Tests if ANY element passes test; short-circuits on first true | Boolean |
Example: Array testing methods
const nums = [2, 4, 6, 8, 10];
const mixed = [1, 2, 3, 4, 5];
// every - all must pass
nums.every(n => n % 2 === 0); // true (all even)
mixed.every(n => n % 2 === 0); // false
nums.every(n => n > 0); // true (all positive)
nums.every(n => n > 5); // false
// some - at least one must pass
mixed.some(n => n % 2 === 0); // true (has even)
mixed.some(n => n > 10); // false
[1, 3, 5].some(n => n % 2 === 0); // false (no even)
// Validation use cases
const users = [
{name: 'Alice', age: 25},
{name: 'Bob', age: 30},
{name: 'Charlie', age: 35}
];
// All adults?
const allAdults = users.every(u => u.age >= 18); // true
// Any seniors?
const hasSeniors = users.some(u => u.age >= 65); // false
// All have names?
const allNamed = users.every(u => u.name && u.name.length > 0);
// Any in 30s?
const hasThirties = users.some(u => u.age >= 30 && u.age < 40);
// Empty array edge cases
[].every(n => n > 100); // true (vacuous truth)
[].some(n => n > 100); // false
// Short-circuit behavior
const expensive = [1, 2, 3, 4, 5];
expensive.every(n => {
console.log('checking', n);
return n < 3;
}); // logs: checking 1, checking 2, checking 3
// stops at 3 (first failure)
expensive.some(n => {
console.log('checking', n);
return n > 3;
}); // logs: checking 1, 2, 3, 4
// stops at 4 (first success)
// Combine with other methods
const valid = users
.filter(u => u.age > 25)
.every(u => u.name.length > 0);
Note:
every() returns true for empty arrays (vacuous truth); some()
returns false. Both short-circuit, stopping iteration early for performance.
7. Array Destructuring and Spread Operator [...]
| Pattern | Syntax | Description | Example |
|---|---|---|---|
| Basic Destructuring | const [a, b] = arr |
Extract elements into variables by position | const [x, y] = [1, 2] |
| Skip Elements | const [a, , c] = arr |
Omit elements with empty comma slots | const [, , z] = [1, 2, 3] |
| Rest Pattern | const [a, ...rest] = arr |
Collect remaining elements; must be last | const [h, ...t] = [1,2,3] |
| Default Values | const [a = 0] = arr |
Provide fallback if undefined; not for null | const [x = 10] = [] |
| Nested Destructuring | const [[a], [b]] = arr |
Destructure nested arrays recursively | const [[x]] = [[1]] |
| Swap Variables | [a, b] = [b, a] |
Elegant variable swap without temp | [x, y] = [y, x] |
| Spread in Array | [...arr] |
Shallow copy or expand iterable | [...arr1, ...arr2] |
| Spread in Call | fn(...arr) |
Pass array elements as separate arguments | Math.max(...nums) |
| Rest in Function | fn(...args) |
Collect function arguments into array | function sum(...n) |
Example: Destructuring and spread patterns
// Basic destructuring
const [a, b, c] = [1, 2, 3];
// a=1, b=2, c=3
// Skip elements
const [first, , third] = [1, 2, 3];
// first=1, third=3
// Rest pattern
const [head, ...tail] = [1, 2, 3, 4];
// head=1, tail=[2,3,4]
const [x, y, ...rest] = [1];
// x=1, y=undefined, rest=[]
// Default values
const [p = 0, q = 0] = [1];
// p=1, q=0
const [m = 'default'] = [undefined];
// m='default' (undefined triggers default)
const [n = 'default'] = [null];
// n=null (null doesn't trigger default!)
// Nested destructuring
const [[a1, a2], [b1, b2]] = [[1, 2], [3, 4]];
// a1=1, a2=2, b1=3, b2=4
// Swap variables
let i = 1, j = 2;
[i, j] = [j, i]; // i=2, j=1
// Function parameters
function sum([a, b]) {
return a + b;
}
sum([3, 4]); // 7
function coords({x, y, z = 0}) {
return [x, y, z];
}
// Spread - shallow copy
const original = [1, 2, 3];
const copy = [...original]; // [1, 2, 3]
// Spread - merge arrays
const arr1 = [1, 2];
const arr2 = [3, 4];
const merged = [...arr1, ...arr2]; // [1,2,3,4]
const combined = [0, ...arr1, 2.5, ...arr2, 5];
// [0, 1, 2, 2.5, 3, 4, 5]
// Spread - function arguments
const nums = [5, 3, 8, 1];
Math.max(...nums); // 8 (instead of apply)
// Rest parameters
function sum(...numbers) {
return numbers.reduce((a, b) => a + b, 0);
}
sum(1, 2, 3, 4); // 10
function first(a, b, ...rest) {
console.log(rest); // array of remaining args
}
// Convert iterable
const set = new Set([1, 2, 3]);
const arr = [...set]; // [1, 2, 3]
const str = 'hello';
const chars = [...str]; // ['h','e','l','l','o']
// Shallow copy warning
const nested = [[1, 2], [3, 4]];
const shallowCopy = [...nested];
shallowCopy[0][0] = 99;
console.log(nested[0][0]); // 99 ❌ (shared reference!)
Warning: Spread creates shallow copy. Nested objects/arrays
share references. Use
structuredClone() for deep copy.
8. Typed Arrays and Buffer Management
| Type | Bytes/Element | Range | Description |
|---|---|---|---|
| Int8Array | 1 | -128 to 127 | Signed 8-bit integer |
| Uint8Array | 1 | 0 to 255 | Unsigned 8-bit integer |
| Uint8ClampedArray | 1 | 0 to 255 (clamped) | Clamped unsigned 8-bit (for Canvas) |
| Int16Array | 2 | -32,768 to 32,767 | Signed 16-bit integer |
| Uint16Array | 2 | 0 to 65,535 | Unsigned 16-bit integer |
| Int32Array | 4 | -2³¹ to 2³¹-1 | Signed 32-bit integer |
| Uint32Array | 4 | 0 to 2³²-1 | Unsigned 32-bit integer |
| Float32Array | 4 | ±1.2×10⁻³⁸ to ±3.4×10³⁸ | 32-bit floating point |
| Float64Array | 8 | ±5.0×10⁻³²⁴ to ±1.8×10³⁰⁸ | 64-bit floating point |
| BigInt64Array | 8 | -2⁶³ to 2⁶³-1 | Signed 64-bit BigInt |
| BigUint64Array | 8 | 0 to 2⁶⁴-1 | Unsigned 64-bit BigInt |
| Buffer API | Syntax | Description | Use Case |
|---|---|---|---|
| ArrayBuffer | new ArrayBuffer(byteLength) |
Fixed-length raw binary data buffer; not directly accessible | Binary data storage |
| DataView | new DataView(buffer, offset, length) |
Low-level interface to read/write multiple types in buffer | Mixed-type binary data |
| SharedArrayBuffer | new SharedArrayBuffer(length) |
Shared memory buffer for Web Workers; requires COOP/COEP headers | Multi-threaded data sharing |
Example: Typed arrays and buffer operations
// Create typed arrays
const uint8 = new Uint8Array(4); // [0, 0, 0, 0]
const int32 = new Int32Array([1, 2, 3]); // [1, 2, 3]
// From ArrayBuffer
const buffer = new ArrayBuffer(16); // 16 bytes
const view32 = new Int32Array(buffer); // 4 elements (16/4)
const view8 = new Uint8Array(buffer); // 16 elements
// Shared buffer - multiple views
view32[0] = 0x12345678;
console.log(view8[0]); // 0x78 (little-endian)
// Array-like operations (limited)
const arr = new Uint8Array([1, 2, 3, 4]);
arr.length; // 4
arr[0]; // 1
arr.slice(1, 3); // Uint8Array[2, 3]
arr.map(x => x * 2); // Uint8Array[2, 4, 6, 8]
// No push/pop/splice - fixed length!
// arr.push(5); ❌ TypeError
// Overflow behavior
const u8 = new Uint8Array(1);
u8[0] = 256; // wraps to 0
u8[0] = -1; // wraps to 255
const clamped = new Uint8ClampedArray(1);
clamped[0] = 256; // clamps to 255
clamped[0] = -1; // clamps to 0
// DataView - mixed types
const buf = new ArrayBuffer(8);
const view = new DataView(buf);
view.setInt8(0, 127); // byte 0: 127
view.setInt16(1, 1000); // bytes 1-2: 1000
view.setFloat32(4, 3.14); // bytes 4-7: 3.14
view.getInt8(0); // 127
view.getInt16(1); // 1000
view.getFloat32(4); // 3.14...
// Endianness control
view.setInt32(0, 0x12345678, true); // little-endian
view.setInt32(0, 0x12345678, false); // big-endian
// Convert regular array
const regular = [1, 2, 3, 4, 5];
const typed = new Int32Array(regular);
// Convert typed to regular
const back = Array.from(typed);
// or [...typed]
// Use cases
// 1. Binary file I/O
fetch('data.bin')
.then(r => r.arrayBuffer())
.then(buf => new Uint8Array(buf));
// 2. WebGL graphics
const vertices = new Float32Array([
-1.0, -1.0,
1.0, -1.0,
0.0, 1.0
]);
// 3. Image processing
const imageData = ctx.getImageData(0, 0, w, h);
const pixels = imageData.data; // Uint8ClampedArray
// RGBA: [r, g, b, a, r, g, b, a, ...]
// 4. Network protocols
const header = new Uint8Array([0x01, 0x02, 0x03, 0x04]);
// SharedArrayBuffer (requires headers)
const shared = new SharedArrayBuffer(1024);
const worker1View = new Int32Array(shared);
const worker2View = new Int32Array(shared);
// Both workers see same memory
Note: Typed arrays are fixed-length, array-like objects for binary data. Use for
performance-critical operations (WebGL, image processing, binary I/O). Regular arrays support more methods and
dynamic sizing.
Section 9 Summary
- Creation: Use literals
[]for general use;Array.from()for iterables with mapper;Array.of()to avoid single-number trap; spread for copying - Mutating:
push/pop(end O(1)),shift/unshift(start O(n)),splice(any position);sortneeds compare function for numbers; these modify original - Non-mutating:
slice(copy),concat(merge),flat/flatMap(flatten); ES2023 addstoSorted/toReversed/toSpliced/withfor immutability - Iteration:
map(transform),filter(select),reduce(accumulate),forEach(side effects); always provide initial value to reduce - Search:
find/findIndex(with predicate),includes(existence, handles NaN),indexOf(position);at()for negative indexing - Testing:
every(all pass),some(any pass); both short-circuit;every([]) === true,some([]) === false - Destructuring:
[a, b] = arr, rest[...rest], skip with,, defaults; spread...arrfor copy/merge (shallow!) - Typed arrays: Fixed-length, type-specific, backed by ArrayBuffer; use for binary data, WebGL, performance; limited methods vs regular arrays