JavaScript Array Methods

An Array on its own is just a container. To make it useful, we need to add items, remove them, find them, or reorganize them. JavaScript provides built-in functions called Methods to handle these tasks.

A key concept in this lesson is Mutability:

  • Mutating Methods: Change the original array directly.
  • Non-Mutating Methods: Leave the original array alone and return a new copy or value.

When working with mutating methods, you can prevent unintended side effects by first creating a shallow copy of the original array using the spread operator ([...]), Array.from(), or .slice(). However, keep in mind that shallow copies only duplicate the top-level structure; if your array contains nested objects or arrays, those internal references still point to the original data. To fully decouple nested structures, you must perform a deep copy using structuredClone() or the older JSON.parse(JSON.stringify()) method, though the latter should be used with caution as it cannot clone special data types like functions or undefined.

These methods directly change the array’s contents and length.

The Stack (End)

  • .push(item): Adds one or more items to the end. Returns the new length.
  • .pop(): Removes the last item. Returns the removed item.
const stack = [1, 2];

stack.push(3); // Add "3" to end of array.
console.log(stack); // Output: [1, 2, 3]

const removed = stack.pop(); // Remove "3" from end of array.
console.log(stack); // Output: [1, 2]
console.log(removed); // Output: 3


// Copy array with ...spread to keep original array intact:
const originalArray = [1, 2, 3];
const copiedArray = [...originalArray];
const pushThis = "four";
copiedArray.push(pushThis);
console.log(originalArray); // Output: [1, 2, 3]
console.log(copiedArray); // Output: [1, 2, 3, "four"]

// Push returns array length without argument in param:
console.log(copiedArray.push());
// Output: 4 (length of array)

/* Note: see "shallow copy" vs. "deep copy" reference above
to know what to use when making copies of your array. */
JavaScript

The Queue (Start)

  • .unshift(item): Adds one or more items to the start. Returns the new length.
  • .shift(): Removes the first item. Returns the removed item.
const queue = ["B", "C"];
queue.unshift("A");
console.log(queue); // Output: ["A", "B", "C"]

const firstItem = queue.shift();
console.log(queue); // Output: ["B", "C"]
console.log(firstItem); // Output: A

console.log(queue.shift()); // Output: B
console.log(queue); // Output: ['C']


console.log(queue.unshift("one", "two"));
// Output: 3 (length of top-level array elements)
console.log(queue); // Output: ['one', 'two', 'C']
JavaScript

The Swiss Army Knife

  • .splice(start, deleteCount, itemsToAdd): Adds, removes, or replaces items anywhere.
const months = ["Jan", "April", "June", "July"];

// .splice(Start Index, Delete Count, Items to Add...)
// Start at index 1 ("April"), delete 0 items, then insert "Feb" and "March"
months.splice(1, 0, "Feb", "March"); 
console.log(months);
// Output: ['Jan', 'Feb', 'March', 'April', 'June', 'July']

// When you omit the second parameter, it deletes EVERYTHING from the Start Index to the end
months.splice(4); 
console.log(months);
// Output: ['Jan', 'Feb', 'March', 'April'] (June & July deleted)

// Start at index 2 ("March"), delete 1 item (which is "March"), then insert "Holiday"
months.splice(2, 1, "Holiday");
console.log(months);
// Output: ['Jan', 'Feb', 'Holiday', 'April']


// Count from the end with a negative splice() start value:
let nums = [1, 2, 3, 4, 5];
nums.splice(-2, 1); // Remove the "4"
console.log(nums); // Output: [1, 2, 3, 5]
nums.splice(-1, 0, 4); // Add "4" back
console.log(nums); // Output: [1, 2, 3, 4, 5]
JavaScript

These methods rearrange the items inside the original array.

  • .reverse(): Reverses the order of the elements in place.
  • .sort(): Sorts the elements in place.
    • Warning: By default, it sorts by string value, meaning 10 comes before 2 because .sort() converts array items to strings by default. You need a “compare function” aka “comparator” callback function for numbers.
// Reverse Array Order
const letters = ["a", "b", "c"];
letters.reverse(); 
console.log(letters);
// Output: ["c", "b", "a"]

// Sort Words - Alphabetical (lexicographically)
console.log(letters.sort());
// Output: ["a", "b", "c"]

// Sort Numbers - Alphabetical (lexicographically) - 10 before 2.
const nums = [5, 1, 10, 2];
nums.sort(); 
console.log(nums); // [1, 10, 2, 5]
JavaScript

To correct number sorting, the .sort() method takes a compare function (callback) which makes .sort() a higher-order function. This can be written as an arrow function (using an implicit return) or a standard function (requiring an explicit return keyword).

The JavaScript engine doesn’t just sort randomly; it passes two items into the callback function parameters ($a, b$) to determine their relationship based on the result: negative (keep $a$ before $b$), positive (move $a$ after $b$), or zero (no change). While this ‘compare-and-swap’ logic is similar to a Bubble Sort, modern engines use Timsort, a more efficient hybrid algorithm that scans for pre-existing patterns (‘runs’) in the data.

Note: Even though the engine’s rules are fixed, you control the outcome with your math. Using a - b creates a negative result when a is smaller (Ascending), while using b - a creates a negative result when a is larger (Descending).

const nums = [5, 1, 10, 2];

nums.sort((a, b) => a - b); // Implicit/Automatic Return
// Ascending (a - b)
console.log(nums); // [1, 2, 5, 10]

nums.sort(function(first, second){
	return second - first // Explicit requires Return
}); // Descending (b - a)
console.log(nums); // Output: [10, 5, 2, 1]

const nameList = ["Bob", "Harry", "Mary", "Ricky Bobby", "Leeroy"]
nameList.sort((short, long) => short.length - long.length)
console.log(nameList);
// Output: ['Bob', 'Mary', 'Harry', 'Leeroy', 'Ricky Bobby']
JavaScript

Instead of using “a – b” for Ascending or “b – a” for Descending with .sort(), we can provide a 1, -1, or 0 value in our callback function to be sorted directly and demystify how the JavaScript Engine interprets the callback. Note: the order in which the engine picks pairs depends on the algorithm’s strategy, but ‘a’ always represents the first item in the comparison pair.

// Ascending Order:
const nums = [5, 1, 10, 2, 10];
const sorting = nums.sort((a, b) => {
	if (a < b) {
		console.log(`Less than: Move ${a} before ${b} = -1`);
		return -1
	} else if (a > b) {
		console.log(`Greater than: Keep ${a} after ${b} = 1`);
		return 1
	} else {
		console.log(`Equal: Keep ${a} after ${b} = 0`);
		return 0
	}
});
console.log(nums); // Output: [1, 2, 5, 10]


// Descending Order:
const nums2 = [5, 1, 10, 2, 10];
const sorting2 = nums2.sort((a, b) => {
	if (a > b) {
		console.log(`Greater than: Move ${a} before ${b} = -1`);
		return -1
	} else if (a < b) {
		console.log(`Less than: Keep ${a} after ${b} = 1`);
		return 1
	} else {
		console.log(`Equal: Keep ${a} after ${b} = 0`);
		return 0
	}
});
console.log(nums2); // Output: [10, 10, 5, 2, 1]
JavaScript

Here’s another example of decoding comparison sorting by console logging the a, b compare sorting. This time we’ll see the value from the comparison instead of 1, -1, or 0.

// Ascending Order
const nums = [5, 2, 8, 1];
console.log(nums);
nums.sort((a, b) => {
	const result = a - b;
	// If result is negative, 'a' (the new item) belongs to the left of 'b'
	const action = result < 0 ? `Move ${a} before ${b}` : `Keep ${a} after ${b}`;
	console.log(`New Item: ${a} | Comparing vs: ${b} | Result: ${result} | Action: ${action}`);
	return result;
}); /*
New Item: 2 | Comparing vs: 5 | Result: -3 | Action: Move 2 before 5
New Item: 8 | Comparing vs: 5 | Result: 3 | Action: Keep 8 after 5
New Item: 1 | Comparing vs: 5 | Result: -4 | Action: Move 1 before 5
New Item: 1 | Comparing vs: 2 | Result: -1 | Action: Move 1 before 2
*/console.log(nums); // Output: [1, 2, 5, 8]


// Descending Order
const nums2 = [5, 2, 8, 1];
nums2.sort((a, b) => {
	const result = b - a;
	// For Descending: Positive means 'b' is bigger, so move 'a' to the right.
	const action = result > 0 ? `Move ${a} (smaller) Right` : `Keep ${a} (larger) Left`;
	console.log(`New: ${a} | Vs: ${b} | Result: ${result} | ${action}`);
	return result;
}); /*
New: 2 | Vs: 5 | Result: 3 | Move 2 (smaller) Right
New: 8 | Vs: 2 | Result: -6 | Keep 8 (larger) Left
New: 8 | Vs: 5 | Result: -3 | Keep 8 (larger) Left
New: 1 | Vs: 5 | Result: 4 | Move 1 (smaller) Right
New: 1 | Vs: 2 | Result: 1 | Move 1 (smaller) Right
*/ console.log(nums2); // Output: [8, 5, 2, 1]
JavaScript

Using .localeCompare() instead of .sort() for Strings (Preferred)

By default, .sort() uses Unicode values. This creates two major issues in professional apps:

  • Case Sensitivity: Uppercase “Z” comes before lowercase “a” (because “Z” has a lower character code).
  • Accents/Special Characters: It doesn’t know that “é” should be treated similarly to “e”.

The localeCompare() method returns the exact numbers that .sort() needs: -1, 1, or 0.

const names = ["Zebra", "apple", "Ángel"];

names.sort();
console.log(names);
// Output: ["Zebra", "apple", "Ángel"] (Unicode order)

names.sort((a, b) => a.localeCompare(b));
console.log(names);
// Output: ["apple", "Ángel", "Zebra"] (Dictionary order)


// Basic localeCompare() comparison without .sort():
const string1 = "apple";
const string2 = "banana";
// 'apple' comes before 'banana' alphabetically.
// The result is a negative number (e.g., -1).
let result1 = string1.localeCompare(string2);
console.log(`"${string1}" compared with "${string2}": ${result1}`);
// Output: "apple" compared with "banana": -1
JavaScript

localeCompare() accepts two optional arguments: locales and options.

  • The locales argument specifies the language whose sort order should be used (i.e en for English, es for Spanish, de for German, or undefined for default). If omitted, the browser’s default locale is used.
  • The options argument is an object that customizes the comparison behavior.
    • Key options (which each have different values of their own) include: usage, sensitivity, ignorePunctuation, numeric, caseFirst and collation.
const items = ["banana", "Apple", "apple"];
items.sort((a, b) => a.localeCompare(b, 'en', { sensitivity: 'base' }));
console.log(items);
// Output: ["Apple", "apple", "banana"] 
// (Treated A and a as the same "base" letter)

const files = ["file10.txt", "file2.txt", "file1.txt"];
files.sort((a, b) => a.localeCompare(b, undefined, { numeric: true }));
console.log(files);
// Output: ["file1.txt", "file2.txt", "file10.txt"]
JavaScript

Real-world example sorting two different values using both .sort() and localeCompare() with a JavaScript Object (covered in next lesson).

const products = [
  { name: "Laptop", category: "Electronics", price: 1200 },
  { name: "Toaster", category: "Appliances", price: 50 },
  { name: "Phone", category: "Electronics", price: 800 },
  { name: "Blender", category: "Appliances", price: 100 }
];

products.sort((a, b) => {
	// 1. First, compare the categories (Alphabetical)
	// localeCompare returns -1, 1, or 0
	const categorySort = a.category.localeCompare(b.category);

	// 2. If categories are NOT the same, use the category order
	if (categorySort !== 0) {
		return categorySort; // Exit function with sorted categories
	}

	// 3. If categories ARE the same (0), use the price to break the tie (Ascending)
	return a.price - b.price; // Exit function w/ sorted categories then price
});

console.log(products);
/* Output:
[
  { name: "Toaster", category: "Appliances", price: 50 },    <- Appliances first
  { name: "Blender", category: "Appliances", price: 100 },   <- Then by price
  { name: "Phone", category: "Electronics", price: 800 },    <- Electronics second
  { name: "Laptop", category: "Electronics", price: 1200 }   <- Then by price
]
*/
JavaScript

Comparing .sort() and localeCompare() Summary:

FeatureDefault .sort()localeCompare()
LogicUnicode Character CodesLanguage-specific dictionary rules
CasesUppercase before lowercaseCase-aware (user-friendly)
AccentsPuts “á” at the very endSorts “á” near “a”
Best ForSimple IDs or SymbolsNames, Titles, and User-facing text

These methods allow you to manipulate data without destroying the original list. They return a brand new array. These methods also work on the string data type.

Slicing & Concatenating

  • .slice(start, end): Returns a copy of a section of an array.
  • .concat(array2): Merges two or more arrays.
const animals = ["Rabbit", "Deer", "Fox", "Bear"];

// Slice (index start, index end):
const wholeArray = animals.slice(0, 4); 
console.log(wholeArray); // Output: ["Rabbit", "Deer", "Fox", "Bear"]

// Parameter #2 is a stop-index (doesn't include index #3):
const middleTwo = animals.slice(1, 3);
console.log(middleTwo); // Output: ['Deer', 'Fox']

// Negatives slice from the end of the array:
const negSlice = animals.slice(0, -1);
console.log(negSlice); // Output: ['Rabbit', 'Deer', 'Fox']

const nestedAnimals = [["Rabbit", "Deer",], ["Fox", "Bear"]];
console.log(nestedAnimals[1].slice(1, 2)); // Output: ["Bear"]
JavaScript
// Concat Method
const birds1 = ["Owl", "Eagle"];
const birds2 = ["Chicken", "Turkey"];
const allBirds = birds1.concat(birds2);
console.log(allBirds); // Output: ['Owl', 'Eagle', 'Chicken', 'Turkey']

const newBird = "Hawk";
const objBird = {Bird: "Falcon"};
console.log(birds1.concat(birds2, newBird, objBird));
// Output: ['Owl', 'Eagle', 'Chicken', 'Turkey', 'Hawk', {Bird: 'Falcon'}]
JavaScript

Transforming (Functional Methods)

These are powerful methods used in modern frameworks like React.

  • .map(fn): transform every item and return a new array of the same length.
  • .filter(fn): Returns a new array containing only items that pass a true/false boolean test.
  • .join(separator): Joins all elements into a single String.
// Map new array with array index plus 10:
console.log([1,2,3].map(x => x + 10));
// Output: [11, 12, 13]


// Map new array with original #s divided by 2:
const numbers = [10, 20, 30];
const doubled = numbers.map(num => num * 2);
console.log(doubled); // Output: [20, 40, 60]


// Map new array rounded with 2 decimals and $ sign:
const prices = [10.5, 20, 35.99];
const formattedPrices = prices.map(price => {
	return `$${price.toFixed(2)}`;
});
console.log(formattedPrices); // Output: ["$10.50", "$20.00", "$35.99"]


// Map new array with uppercase strings:
const names = ["toronto", "london", "new york"];
const upperCaseNames = names.map(name => name.toUpperCase());
console.log(upperCaseNames); // Output: ["TORONTO", "LONDON", "NEW YORK"]


// Map new array with square root of index:
const numbers2 = [4, 9, 16, 25];
const roots = numbers2.map(Math.sqrt);
console.log(roots); // Output: [2, 3, 4, 5]


// Map/extract Object Properties in array to new array:
const gameResults = [
	{id: 1, userName: "Rodney", console: "PC"},
	{id: 2, userName: "Dersha", console: "PS5"},
	{id: 3, userName: "Beck", console: "Nintendo"}
];
const userInfo = gameResults.map(user => user.console);
console.log(userInfo); // Output: ['Rodney', 'Dersha', 'Beck']


// Map/add a New Object Property to a new array:
const products = [
	{name: "iPhone", price: "1,200"},
	{name: "Android", price: "800"},
	{name: "Laptop", price: "2,200"}
];
const productsWithTax = products.map(product => {
	return {
		...product,
		productsWithTax: product.price.replace(',','') * 1.2
		// Type Coercion converts string to number without comma
	};
});
console.log(productsWithTax)
/* Output: [
{name: 'iPhone', price: '1,200', productsWithTax: 1440}
{name: 'Android', price: '800', productsWithTax: 960}
{name: 'Laptop', price: '2,200', productsWithTax: 2640}
] */


// Map with additional parameter/argument:
const items = ['apple', 'banana', 'cherry'];
// "index","item","array" are built-in parameters with map()
// They must be in this order (item, index, array)
// (item, index) can be used without the "array" param
const indexedItems = items.map((item, index, array) => {
	return `Item at index ${index}: ${item} | Array: ${array}`;
});
console.log(indexedItems); 
/* Output: [
	'Item at index 0: apple | Array: apple,banana,cherry',
	'Item at index 1: banana | Array: apple,banana,cherry',
	'Item at index 2: cherry | Array: apple,banana,cherry'
] */
JavaScript
// Filter new array with numbers >= 10
const numbers = [13, 5, 10, 6, 18];
const greaterThanTen = numbers.filter(num => num >= 10);
console.log(greaterThanTen); // Output: [13, 10, 18]


// Filter new array with even numbers
//const numbers = [13, 5, 10, 6, 18];
const myCallback = (pass2callback) => {
	return pass2callback % 2 === 0;
};
const evenNumbers = numbers.filter(myCallback);
console.log(evenNumbers); // Output: [10, 6, 18]


// Filter an array of unique numbers by checking for the first index of a number.
const numArray = [13, 5, 10, 13, 6, 18, 5];
// "item" (or currentValue): The current element being processed in the array. This is the first argument provided to the callback function.
// "index" (or currentIndex): The index of the current element being processed. This is the second argument.
// "array" (or arrayRef): A reference to the original array that filter was called upon. This is the third argument.
const uniqueNumbers = numArray.filter((item, index, array) => {
	// .indexOf(item) always returns the VERY FIRST index where it finds the item
	const firstPosition = array.indexOf(item);

	// LOGIC: If the current index is the same as the first position, it's the original.
	// If they are different, it means we've seen this item before (it's a duplicate).
	const isOriginal = index === firstPosition;

	console.log(`Item: ${item} | Index: ${index} | First Seen At: ${firstPosition} | Keep? ${isOriginal}`);

	return isOriginal;
});
/* Item: 13 | Index: 0 | First Seen At: 0 | Keep? true
Item: 5 | Index: 1 | First Seen At: 1 | Keep? true
Item: 10 | Index: 2 | First Seen At: 2 | Keep? true
Item: 13 | Index: 3 | First Seen At: 0 | Keep? false
Item: 6 | Index: 4 | First Seen At: 4 | Keep? true
Item: 18 | Index: 5 | First Seen At: 5 | Keep? true
Item: 5 | Index: 6 | First Seen At: 1 | Keep? false */
console.log(uniqueNumbers); // Output [13, 5, 10, 6, 18]
JavaScript
// Joining arrays keeps the comma by default:
const colors = ["red", "blue", "green"];
console.log(colors.join());
// Output: red,blue,green


// Join an array and replace the comma with a dash:
const myNums = [2, 3, 4,];
const csv = myNums.join("-");
console.log(csv); // Output: 2-3-4


// Join array items without the comma:
const letters = ["H", "e", "l", "l", "o"];
console.log(letters.join(""));
// Output: Hello


// Joining null or undefined items are treated as empty strings:
const data = [1, undefined, "String", null, 3];
console.log(data.join());
// Output: 1,,Hello,,3
JavaScript

Methods to locate specific items or their positions.

  • .includes(item): Returns true if the item exists.
  • .indexOf(item): Returns the index of the first match (or -1).
  • .find(fn): Returns the first item that satisfies a testing function.
  • .findIndex(fn): Returns the index of the first item that satisfies a testing function.
// includes() String Method Reminder:
const colors = "red, blue, green";
console.log(colors.includes(", blue")); // Output: true
console.log(colors.includes("Red")); // Output: false
// includes() is case sensitive.


// includes() Array Method:
const numbers = [10, 20, 30, 40, 50];
console.log(numbers.includes(30)); // Output: true
console.log(numbers.includes(31)); // Output: false


// Search for 30 starting from index 3
console.log(numbers.includes(30, 3));
// Output: false (because 30 appears before index 3)
console.log(numbers[3]); // Output: 40


// Search for 40 starting from index 3
console.log(numbers.includes(40, 3));
// Output: true
JavaScript
// indexOf() String Method Reminder:
const newColors = "black, purple, brown";
console.log(newColors.indexOf("B"));
// Output: -1 (case sensitive)
console.log(newColors.indexOf("b"));
// Output: 0 (returns the first index of the character)


// indexOf() Array Method:
const fruits = ["orAnge", "apple", "banana"];
console.log(fruits.indexOf("apple")); // Output: 1


// Mapping a new array toLowerCase to address case sensitivity:
console.log(fruits.map(fruit => fruit.toLowerCase()).indexOf("orange"));
// Output: 0 (now that the array is all lowercase)


// indexOf() from a specific index:
const numberInd = [10, 20, 30, 40, 20, 50];
console.log(numberInd.indexOf(20, 2));
// Output: 4 (starts search at index 2 (30), finds "20" at index 4)


// Check user permissions with indexOf():
const userDetails = [
	{ profile: "public" },
	{ permissions: ["read", "write", "delete"] },
	{ darkMode: true },
];
if (userDetails[1].permissions.indexOf("write") !== -1) {
	// Execute "write" permissions code.
	console.log("User has write permissions.");
}
if (userDetails[1].permissions.indexOf("delete") !== -1) {
	// Execute "delete" permissions code.
	console.log("User has delete permissions.");
}
JavaScript
/* .find() Array Method:
(element, index, array)
element (or currentValue): The current element being processed in the array.
index (optional): The index of the current element being processed.
array (optional): The original array that find() was called upon. */

// Finding the first number > 10:
const numbers = [5, 12, 8, 130, 44];
const found = numbers.find(element => element > 10);
console.log(found); // Output: 12


// Find the first string with .toLowerCase() for case sensitivity:
const sports = ["Football", "Baseball", "Hockey", "Baseketball"];
const findSport1 = sports.find(sport => sport.includes("base"));
console.log(findSport1); // Output: undefined
const findSport2 = sports.find(sport => sport.toLowerCase().includes("base"));
console.log(findSport2); // Output: Baseball


// Find the first string that starts with "m"
const trees = ["birch", "maple", "oak", "poplar"];
const result = trees.find(tree => tree.startsWith("m"));
console.log(result); // Output: "maple"
// .startsWith() Example (case sensitive):
console.log("Hello".startsWith("We")); // Output: false
console.log("Hello".startsWith("He")); // Output: true


// Finding complex data (like objects)
const people = [
	{id: 1, name: "Jen"},
	{id: 2, name: "Bob"}
];
// Find the actual object
const findBob = people.find(person => person.id === 2);
console.log(findBob); // {id: 2, name: "Bob"}


// Finding items with a price less than 600:
const items = [
	{ name: "Laptop", price: 1000 },
	{ name: "Tablet", price: 500 },
	{ name: "Phone", price: 300 }
];
const affordableItem = items.find(item => item.price < 600);
console.log(affordableItem); // Output: { name: "Tablet", price: 500 }


// Reminder: to return all matches, use .filter() instead of .find():
const affordableItem2 = items.filter(item => item.price < 600);
console.log(affordableItem2);
// Output: { name: "Tablet", price: 500 } { name: "Phone", price: 300 }


// Finding number with element and index:
const numbersTwo = [5, 12, 8, 130, 44];
const foundNum = numbersTwo.find((element, index) => {
	// If there is a number with a remainder of 0
	// AND the array index is greater than 1 (1 index is 12)
	const isTrue = element % 2 === 0 && index > 1;
	return isTrue;
});
console.log(foundNum); // Output: 8


// Using all three (element, index, array) parameters:
// Find the first temperature that is higher than the one BEFORE it
const temps = [77, 72, 68, 85, 90];
const spike = temps.find((element, index, array) => {
	// Skip the first index because there's no previous array to compare.
	if (index === 0) return false;
	// Get the previous array to compare to current element
	const previous = array[index - 1]; 
	return element > previous;
});
console.log(spike); // Output: 85 (Because 85 > 68)
JavaScript
/* .findIndex() Array Method:
(element, index, array)
element (or currentValue): The current element being processed in the array.
index (optional): The index of the current element being processed.
array (optional): The original array that find() was called upon. */


// Find the index of the first occurrence of the number 7
const numbers = [3, 1, 4, 5, 7, 8, 10, 7];
const index = numbers.findIndex(element => element === 7);
console.log(index);
// Output: 4
// (The first 7 is at index 4)


const index2 = numbers.findIndex(element => {
	const findIt = element < 7 && element % 2 === 0;
	return findIt;
});
console.log(index2);
// Output: 2 (index 2)


// Find the object property index in an array:
const people = [
	{id: 11, name: "Bob"},
	{id: 22, name: "Beck"},
	{id: 33, name: "Barry"}
];
const barryIndex = people.findIndex(person => person.id === 33);
console.log(barryIndex); // Output: 2 (index 2)


// .findIndex() with all three parameters (element, index, array):
const languages = ["HTML", "CSS", "JavaScript", "React"];
let targetIndex = languages.findIndex((element, index, array) => {
	// Logging will show how many iterations to get to the desired index:
	console.log(`Element: ${element} | Index: ${index} | Array: ${array.join(" ")}`);
	// The condition accesses the array via the 'array' parameter:
	return array[index] === "CSS";
});
console.log(`The index of JavaScript is: ${targetIndex}`);
/* Output:
Element: HTML | Index: 0 | Array: HTML CSS JavaScript React
Element: CSS | Index: 1 | Array: HTML CSS JavaScript React
The index of CSS is: 1 */


// Find Index of an element < leftElement && element < rightElement:
const data = [10, 20, 5, 50, 40];
const localMinimumIndex = data.findIndex((element, index, array) => {
	const leftNeighbor = array[index - 1];
	const rightNeighbor = array[index + 1];
	// Check if it has both left and right neighbors and is smaller than both
	if (index > 0 && index < array.length - 1) {
		return element < leftNeighbor && element < rightNeighbor;
	}
	return false;
});
console.log(localMinimumIndex);
// Output: 2 (The element 5 at index 2 is smaller than 20 and 50)
JavaScript
  • .some(fn): Returns true if at least one item passes the test.
  • .every(fn): Returns true only if ALL items pass the test.
  • .reduce(fn, initialValue): Reduces the array to a single value (like a total sum).
/* .some() Array Method:
(element, index, array)
element (or currentValue): The current element being processed in the array.
index (optional): The index of the current element being processed.
array (optional): The original array that find() was called upon. */


// .some() - is there an element equal to 3:
const numbers = [1, 2, 4, 5];
const index = numbers.some(element => element === 3);
console.log(index);
// Output: false (there is no "3")


// .some() - is there an element with index > 2 and even:
const index2 = numbers.some((element, index) => {
	const findIt = index > 1 && element % 2 === 0;
	return findIt;
});
console.log(index2);
// Output: true 


// .some() with all three parameters (element, index, array):
const languages = ["HTML", "CSS", "JavaScript", "React"];
let targetIndex = languages.some((element, index, array) => {
	// Logging will show how many iterations to get to find true condition:
	console.log(`Element: ${element} | Index: ${index} | Array: ${array.join(" ")}`);
	// The condition accesses the array via the 'array' parameter:
	return array[index] === "CSS";
});
console.log(targetIndex);
/* Output:
Element: HTML | Index: 0 | Array: HTML CSS JavaScript React
Element: CSS | Index: 1 | Array: HTML CSS JavaScript React
true */
JavaScript
/* .every() Array Method:
(element, index, array)
element (or currentValue): The current element being processed in the array.
index (optional): The index of the current element being processed.
array (optional): The original array that find() was called upon. */

// .every() Check if every element meet the condition:
const scores = [80, 90, 100];
// Is every() number greater than 60?
const allGreater = scores.every(element => element > 60);
console.log(allGreater); // true
// Is every() number even (remainder of 0 when divided by 2)?
const allEven = scores.every(element => element % 2 === 0);
console.log(allEven); // true

const names = ["Bobby", "Sandy", "Willy"];
// Does every() name include the letter "a"?
const allAChar = names.every(element => element.includes("a"));
console.log(allAChar); // false
// Does every() name include the letter "y"?
const allYChar = names.every(element => element.includes("y"));
console.log(allYChar); // true
JavaScript
/* .reduce() has 4 total parameters:
(accumulator, currentValue, index, array)
with index & array being optional.
*/

// Calculate Total (Accumulator starts at 90)
const scores = [80, 90, 100];
const total = scores.reduce((total, score) => total + score, 90);
console.log(total); // 360 (270, 90 = 360)

// Reduce's 4 parameters in use while logging the process:
const initialValue = 90;
const newTotal = scores.reduce((accumulator, currentValue, index, array) => {
	// Create a visual folder for each step
	console.group(`Iteration ${index + 1}`);
	console.log(`Accumulator: ${accumulator}`);
	console.log(`Current Value: ${currentValue}`);

	const sum = accumulator + currentValue;

	console.log(`Iteration end: ${sum}`);
	//console.log(`(Same Array: ${array})`);
	console.groupEnd(); // Close the folder

	return sum;
}, initialValue);
console.log(`Final Result: ${newTotal}`);


const newScores = [2, 1, 5, 10, 8];
// Skip current values less than or equal to 5:
const newTotal2 = newScores.reduce((accumulator, currentValue) => {
	if (currentValue <= 5) {
		currentValue = 0;}
		return accumulator + currentValue
	}, 0);
console.log(newTotal2); // Output 18

// Better Way to skip currentValue's with a condition:
const newTotal3 = newScores
   .filter(score => score > 5)   // [10, 8]
   .reduce((accumulator, currentValue) => accumulator + currentValue, 0); // 18
console.log(newTotal3); // Output: 18

// Ternary Way to skip currentValue's with a condition:
const newTotal4 = newScores.reduce((accumulator, currentValue) => {
   return currentValue > 5 ? accumulator + currentValue : accumulator;
}, 0);
console.log(newTotal4); // Output: 18


// Using .reduce() to sum values in an Array of Objects:
const startingValue = 0;
const myObjects = [{ num: 1 }, { num: 2 }, { num: 3 }];
const numSum = myObjects.reduce(
	(accumulator, currentValue) => accumulator + currentValue.num,
	startingValue
);
console.log(numSum); // Output: 6


// Flattening A Multidimensional Array with .reduce() loop:
const multiArray = [
  ['Bob', 'Bill'],
  ['Beck', 'Barry'],
  ['Ben', 'Brad'] ];
const flattenNames = multiArray.reduce((accumulator, currentArray) =>
	accumulator.concat(currentArray));
console.log(flattenNames);
// ['Bob', 'Bill', 'Beck', 'Barry', 'Ben', 'Brad']

// Manually flattening instead of looping and adding indexes 1 by 1:
const conc = [];
console.log(conc.concat(multiArray[0],multiArray[1],multiArray[2]));


// Counting Occurrences of Items in an Array:
const arrayItems = ["car", "house", "boat", "house", "car"];
const checkOccurrences = arrayItems.reduce((accumulator, currentValue) => {
	// Loop 1: currentValue is "car" using initial empty object as lookup table.
	// The code becomes: accumulator["car"] = (undefined || 0) + 1;
	// The object now looks like: { car: 1 }
	// "0" is used so the value is never undefined which would stop the loop.
	accumulator[currentValue] = (accumulator[currentValue] || 0) + 1;
	// ^^^^^ OBJECT KEY ^^^^^    ^^^^^^^^^ OBJECT VALUE ^^^^^^^^^^^^^
	return accumulator;
}, {}); // Empty object as the initial value.
console.log(checkOccurrences);
// Final Output: {car: 2, house: 2, boat: 1}

// Simple way with one line:
const oneLineOccurrences = arrayItems.reduce((acc, curr) => (acc[curr] = (acc[curr] || 0) + 1, acc), {});
console.log(oneLineOccurrences); // Output: {car: 2, house: 2, boat: 1}


// Grouping Objects by a Property
const foodItems = [
  { name: 'Apple', category: 'Fruit' },
  { name: 'Onion', category: 'Vegetable' },
  { name: 'Orange', category: 'Fruit' },
  { name: 'Lettuce', category: 'Vegetable' }
];
const groupedItems = foodItems.reduce((accumulator, currentItem) => {
	const category = currentItem.category;
	// Check to see if the accumulator already has an
	// object key named after the current category.
	// Skip if object.category has been seen by accumulator before:
	if (!accumulator[category]) {
		// If missing, initialize an empty array for each
		// unique Object category value (Fruit, Vegetable)
		// inside of the initialized empty accumulator object {}:
		accumulator[category] = [];
		// { Fruit: [], Vegetable: [] }
	}
	// Push the currentItem { name: 'Apple', category: 'Fruit' } to the
	// new empty arrays by category:
	accumulator[category].push(currentItem);
	// Alternatively you could just add the name property value:
	//accumulator[category].push(currentItem.name);
	return accumulator;
}, {});
console.log(groupedItems);
/* Output:
{
	Fruit: [ { name: 'Apple', category: 'Fruit' }, { name: 'Orange', category: 'Fruit' } ],
	Vegetable: [ { name: 'Onion', category: 'Vegetable' }, { name: 'Lettuce', category: 'Vegetable' } ]
}
*/
JavaScript
  • .forEach(fn): Executes a function for every item. It does not return a new array (unlike .map).
  • .length: A property (not a method) returning the count of items.
// .forEach() takes up to three parameters (element, index, array):

const cities = ["Paris", "Tokyo"];
cities.forEach(city => console.log(`Traveling to ${city}`));
// Output: Traveling to Paris... Traveling to Tokyo...


const colors = ['red', 'green', 'blue'];
colors.forEach((color, index) => {
	console.log(`Color at index ${index} is ${color}`);
});
// Output:
// Color at index 0 is red
// Color at index 1 is green
// Color at index 2 is blue


// Using all three parameters:
const numbers = [10, 20, 30];
let sum = 0;
numbers.forEach(function(number, index, originalArray) {
	sum += number;
	console.log(`Element ${number} | Index: ${index} | Array [${originalArray}]`);
});
console.log(`Total sum: ${sum}`);
/* Output:
Element 10 | Index: 0 | Array [10,20,30]
Element 20 | Index: 1 | Array [10,20,30]
Element 30 | Index: 2 | Array [10,20,30]
Total sum: 60
*/


let arrayOfObjects = [
	{ name: 'Alice', age: 25 },
	{ name: 'Bob', age: 30 },
];
arrayOfObjects.forEach(obj => {
	// Add a new property to each object
	obj.newProperty = 'some value';
});
console.log(arrayOfObjects);
/* Output:
[
  { name: 'Alice', age: 25, newProperty: 'some value' },
  { name: 'Bob', age: 30, newProperty: 'some value' }
] */
JavaScript
// .length can be used for string and arrays:

// String Example:
console.log("String".length);
// Output: 6


// Array Example:
console.log([1,2,3].length);
// Output: 3


// Using logic based on an arrays length:
const numbers = [1, 2, 3, 4, 5];
if (numbers.length > 3) {
  numbers.length = 3; 
}
console.log(numbers); // Output: [1, 2, 3]


// Filtering and checking array length:
const users = ['Bob', 'Bill', 'Charlie', 'David'];
const filteredUsers = users.filter(user => user.startsWith('B'));
if (filteredUsers.length > 0) {
	console.log('Found users starting with B:', filteredUsers);
} else {
	console.log('No users found.');
}
// Output: Found users starting with B: ['Bob', 'Bill']
JavaScript
MethodBasic / AdvancedDescriptionMutates?Returns
.push()BasicAdd to end✅ YesNew Length
.pop()BasicRemove from end✅ YesRemoved Item
.unshift()BasicAdd to start✅ YesNew Length
.shift()BasicRemove from start✅ YesRemoved Item
.splice()BasicAdd/Remove/Replace middle✅ YesArray of removed items
.sort()AdvancedSort items✅ YesThe sorted array
.reverse()BasicReverse order✅ YesThe reversed array
.map()AdvancedTransform every item❌ NoNew Array (Same Length)
.filter()AdvancedSelect specific items❌ NoNew Array (Subset)
.reduce()AdvancedCalculate single value❌ NoSingle Value (Sum, Obj, etc)
.concat()BasicMerge arrays❌ NoNew Combined Array
.slice()BasicCopy a portion❌ NoNew Array Copy
.join()BasicConvert to String❌ NoString
.find()AdvancedFind an item by logic❌ NoThe Item (or undefined)
.findIndex()AdvancedFind index by logic❌ NoIndex Number (or -1)
.indexOf()BasicFind index by value❌ NoIndex Number (or -1)
.includes()BasicCheck existence❌ NoBoolean (true/false)
.some()AdvancedCheck if ANY match❌ NoBoolean (true/false)
.every()AdvancedCheck if ALL match❌ NoBoolean (true/false)
.forEach()AdvancedLoop through items❌ Noundefined (Nothing)
.lengthBasicCount of items❌ NoNumber

Why This Matters: In modern software engineering, the ability to efficiently manipulate data with array methods is often what separates a working script from a scalable, professional application.