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); sort needs compare function for numbers; these modify original
  • Non-mutating: slice (copy), concat (merge), flat/flatMap (flatten); ES2023 adds toSorted/toReversed/toSpliced/with for 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 ...arr for copy/merge (shallow!)
  • Typed arrays: Fixed-length, type-specific, backed by ArrayBuffer; use for binary data, WebGL, performance; limited methods vs regular arrays