close icon
daily.dev platform

Discover more from daily.dev

Personalized news feed, dev communities and search, much better than whatโ€™s out there. Maybe ;)

Start reading - Free forever
Start reading - Free forever
Continue reading >

Prototype Array Methods: A Comprehensive Guide

Prototype Array Methods: A Comprehensive Guide
Author
Nimrod Kramer
Related tags on daily.dev
toc
Table of contents
arrow-down

๐ŸŽฏ

Explore a comprehensive guide to prototype array methods in JavaScript, including accessor, iteration, mutator, and ES2023 methods. Understand the prototype chain, performance considerations, and customization tips.

JavaScript's Array objects come equipped with a suite of prototype methods that make manipulating and managing arrays significantly more manageable. These methods fall into different categories, each serving unique purposes, from accessing and modifying array elements to iterating over them. Here's a quick overview:

  • Accessor Methods: Methods like concat(), includes(), slice(), and join() let you view and combine array elements without altering the original array.
  • Iteration Methods: Functions such as forEach(), map(), filter(), and reduce() allow you to process elements in an array to generate new data or aggregated results.
  • Mutator Methods: Methods including push(), pop(), shift(), and splice() modify the array by adding or removing elements.
  • ES2023 Methods: New additions like toReversed(), toSorted(), toSpliced(), and with() introduce more versatile ways to handle arrays directly and efficiently.

These tools not only simplify data manipulation but also promote code readability and reusability. While extending Array.prototype with custom methods can offer tailored solutions, it's generally advisable to proceed with caution to avoid potential conflicts or performance issues. Understanding and utilizing these built-in array methods can significantly enhance your JavaScript coding efficiency and effectiveness.

The Prototype Chain

Think of the prototype chain like a ladder in JavaScript that helps objects share features. Every JavaScript object has a hidden link called [[Prototype]] that connects it to another object, its prototype.

For arrays, this chain looks like this:

[] ---> Array.prototype ---> Object.prototype ---> null

This means the array's prototype is Array.prototype, which then links to Object.prototype. When you use a method like map() on an array:

  1. JavaScript first checks the array itself.
  2. If it's not there, it looks in Array.prototype
  3. If still not found, it moves up the chain until it finds it.

This setup lets all arrays use methods from the array prototype, even if those methods weren't directly added to them.

Why Array.prototype Matters

Interacting with Array.prototype is useful because:

  • Reusability - Add a method once to Array.prototype, and all arrays will have it.
  • Optimized implementations - The built-in methods are designed to be fast.
  • Easy extension - You can add new capabilities to arrays with something like Array.prototype.myCustomMethod = function() {}.

However, adding your own methods to Array.prototype can cause problems, like making it harder to find properties or risking conflicts with new JavaScript features.

So, while it's possible to add to Array.prototype, it's important to be careful and think about whether it's really necessary.

Performance Considerations

Adding to Array.prototype can slow things down because:

  • New functions are added to all arrays, which can be overkill
  • It can make finding properties slower because there's more to look through
  • There's a chance of naming conflicts with future updates in JavaScript

So, even though it might be tempting to add your own methods to Array.prototype, it's usually better to avoid it. Instead, try using methods that are already available or define them on specific arrays or subclasses to keep things running smoothly.

Comprehensive Guide to Prototype Array Methods

Accessor Methods

Accessor methods help you get and look at data in arrays without changing the original array itself. Here are some common ones:

concat() - Puts two or more arrays together into one new array.

const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6]; 

arr1.concat(arr2); // [1, 2, 3, 4, 5, 6]

includes() - Checks if an array has a certain value. It gives back true or false.

[1, 2, 3].includes(2); // true

indexOf() - Finds the first place a value shows up in an array, or -1 if it's not there.

[1, 2, 3].indexOf(3); // 2

join() - Puts all elements of an array into a string, separated by whatever you choose.

[1, 2, 3].join("-"); // "1-2-3" 

slice() - Gives back a piece of an array from one point to another.

[1, 2, 3].slice(1, 3); // [2, 3]

Iteration Methods

Iteration methods go through each item in an array and can give back a new value. Here are some you'll see a lot:

forEach() - Runs a function on each item in the array. Great for when you need to do something with each item.

[1, 2, 3].forEach(x => console.log(x)); 
// 1 
// 2
// 3

map() - Makes a new array by running a function on every item in the original array.

[1, 2, 3].map(x => x * 2); // [2, 4, 6]  

filter() - Creates a new array with only the items that pass a certain test.

[1, 2, 3].filter(x => x > 1); // [2, 3] 

reduce() - Turns an array into a single value by running a function on each item, one after the other.

[1, 2, 3].reduce((acc, x) => acc + x, 0); // 6

Mutator Methods

Mutator methods change the original array. Here are some examples:

push() - Adds new items to the end of an array. It tells you the new size of the array.

let arr = [1, 2];
arr.push(3); // arr = [1, 2, 3]  

pop() - Takes off the last item of an array and gives it back.

let arr = [1, 2, 3]; 
arr.pop(); // arr = [1, 2];

shift() - Removes the first item of an array and gives it back.

let arr = [1, 2, 3];
arr.shift(); // arr = [2, 3];  

unshift() - Puts new items at the start of an array. It tells you the new size of the array.

let arr = [2, 3]; 
arr.unshift(1); // arr = [1, 2, 3];

splice() - Adds or removes items from an array and gives back any items that were taken out.

let arr = [1, 2, 3, 4];
arr.splice(1, 2); // arr = [1, 4];

New ES2023 Methods

ES2023 brought in some new methods for Array.prototype that are pretty handy:

toReversed() - Turns the order of the elements around right in the spot.

let arr = [1, 2, 3];
arr.toReversed(); // arr = [3, 2, 1]

toSorted() - Puts the elements in order right where they are.

let arr = [3, 1, 2];  
arr.toSorted(); // arr = [1, 2, 3]

toSpliced() - Adds or takes out elements just like splice() but does it right in place.

let arr = [1, 2, 3, 4];   
arr.toSpliced(1, 2, 5, 6); // arr = [1, 5, 6, 4]

with() - Lets you chain array methods together without needing extra variables.

[1, 2, 3].with().reverse().map(x => x * 2); // [6, 4, 2]

These new methods make working with arrays smoother without changing the original.

Customizing Array.prototype

Adding your own tricks to Array.prototype might seem cool, but it's usually best to avoid it unless you really have to. Here's how to do it safely if you need to:

Only Add Methods When Absolutely Necessary

When you add methods to Array.prototype, every array gets them. This can make things slower and cause clashes with new updates in JavaScript. Add a method only if you're going to use it a lot.

Check for Existing Methods First

Before you add something new, make sure it doesn't already exist in Array.prototype or in other JavaScript libraries. This helps avoid adding the same thing twice under different names.

Use Unique, Descriptive Method Names

Pick clear and specific names for your methods, like arrayToCSV() instead of just convert(). This helps avoid mix-ups with other libraries and makes it easier to understand what the method does.

Document Custom Methods

Explain how your custom methods work with comments that include what they do, the arguments they take, what they return, and some examples. This helps other developers use them correctly.

Consider Subclasses or Utility Functions Instead

Instead of adding methods to Array.prototype for everyone, think about making array subclasses or just separate functions. This way, you only add new behaviors where they're needed.

For example, instead of:

Array.prototype.double = function() {
  return this.map(x => x * 2); 
}

[1, 2, 3].double();

Do:

function doubleArray(arr) {
  return arr.map(x => x * 2);  
}

doubleArray([1, 2, 3]);

This approach keeps your double logic in one place, without adding it to all arrays.

So, think twice before you add new methods to Array.prototype. If you decide to go ahead, pick unique names, document well, and use subclasses or separate functions when you can. This keeps everything tidy and avoids unnecessary changes to all arrays.

Advanced Topics

Array.prototype is an Array

Did you know Array.prototype is actually an array itself? This is a bit like saying the rule book for arrays is also an array. It's pretty neat because it means you can use array methods directly on Array.prototype, like this:

Array.prototype.map()
Array.prototype.filter()

But, we have to be careful with this power. Changing the basic rules for all arrays can slow things down or cause other issues.

New Array Methods in ES2022

In 2022, JavaScript got two cool new array methods:

  • Array.prototype.unique() - This gets rid of duplicates in an array and gives you a fresh array without them:

    [1, 2, 2, 3].unique(); // [1, 2, 3]
    
  • Array.prototype.partition() - This splits an array into two based on whether the items pass a test or not:

    [1, 2, 3, 4].partition(x => x % 2 === 0);
    // [[2, 4], [1, 3]]
    

These help make working with arrays even easier, but remember, changing arrays directly can make your code tricky to follow. It's often better to use methods that don't change the original array, like map(), filter(), and slice().

Subclasses for Custom Array Behavior

If you want to add your own special features to arrays, creating subclasses is a smart move. Here's how:

class CustomArray extends Array {
  shout() {
    return this.map(x => x.toUpperCase());
  }
}

let arr = new CustomArray();
arr.shout();

This way, you can add new features to your arrays without messing with all arrays everywhere. Subclasses are great because they let you add what you need without the downsides like:

  • Slowing things down by adding extra steps in loops
  • Conflicts with new features in JavaScript
  • Problems with code that expects arrays to work the standard way

So, for adding new array features, subclasses are usually the better choice over changing Array.prototype directly.

Practical Applications and Examples

Prototype array methods are super helpful when you're coding in JavaScript. Let's look at some everyday uses:

Formatting and Displaying Data

The join(), toLocaleString(), and toString() methods are great for turning array data into a format that's easy to read:

// Turn array values into a string with commas
let fruits = ['Apple', 'Banana', 'Orange'];
fruits.join(', '); // 'Apple, Banana, Orange'

// Make array values match local format
let prices = [1.23, 4.56, 7.89]; 
prices.toLocaleString(); // '1.23, 4.56, 7.89'

Filtering Data

The filter() method lets you pick out specific items from an array:

// Keep only even numbers
let numbers = [1, 2, 3, 4];
numbers.filter(n => n % 2 === 0); // [2, 4]

// Keep tasks that aren't done yet
let tasks = [{...}, {...}]; 
tasks.filter(task => !task.completed); 

Transforming Data

map() changes each item in an array into something new:

// Make all numbers twice as big  
let numbers = [1, 2, 3];
numbers.map(n => n * 2); // [2, 4, 6]

// Get just the names out of a list of people
let people = [{name: 'John'}, {name: 'Sarah'}]; 
people.map(person => person.name); // ['John', 'Sarah']

Reducing to Values

reduce() turns a whole array into just one value:

// Add all numbers together
let numbers = [1, 2, 3]; 
numbers.reduce((prev, curr) => prev + curr, 0); // 6

// Make one big array out of nested arrays
let arrays = [[1, 2], [3, 4], [5, 6]];
arrays.reduce((acc, array) => acc.concat(array), []); // [1, 2, 3, 4, 5, 6]  

Chaining Methods

You can put prototype methods in a row to work on data step by step:

// Keep even numbers, then double them
let numbers = [1, 2, 3, 4]; 

numbers
  .filter(n => n % 2 === 0)
  .map(n => n * 2); // [4, 8]
  
// Turn people's ages into a total age
let people = [{age: 20}, {age: 30}];  

people
  .map(person => person.age)
  .reduce((total, age) => total + age, 0); // 50

The .with() method from ES2023 makes putting methods together like this even easier.

So, learning how to use these array methods is really useful for making your code do exactly what you want, in a neat and efficient way.

sbb-itb-bfaad5b

Conclusion

Prototype array methods are super helpful when you're dealing with lists in JavaScript. By learning methods like map(), filter(), reduce(), and others, you get to work with lists in a much easier and powerful way.

Here's what you should remember:

  • Prototype methods mean that all lists can automatically do things like join() and slice(). This makes your code easier to use again, faster, and more predictable.

  • There are different kinds of methods for specific tasks, such as:

    • Getting info from lists with methods like concat(), includes(), and slice()
    • Going through lists item by item with forEach(), map(), filter(), and reduce()
    • Changing lists directly with push(), pop(), shift(), and others
  • The latest methods like toReversed() and toSorted() from ES2023 let you change lists right where they are.

  • Even though you can add your own stuff to Array.prototype, it's usually better to be careful and use utility functions or subclasses instead.

  • These prototype methods are great for:

    • Making lists look nice, picking out certain items, and combining items into one value
    • Linking different actions together to work on data step by step
    • Keeping things simple without needing lots of loops

In simple terms, knowing these built-in JavaScript methods makes working with lists much easier. Practice the main ones we talked about until you're comfortable with them.

Lists are a big part of programming, so being good at these methods can really help make your code cleaner and more efficient.

Further Reading & Resources

Here are some good places to learn more about how JavaScript uses prototypes and inheritance, and how to work with arrays:

Prototypes and Inheritance

  • Object prototypes - A guide that breaks down what prototypes are in a way that's easy to understand.
  • Inheritance and the prototype chain - Explains how objects inherit features from each other using the prototype chain.
  • Object.create() - Shows how to use Object.create() to set up inheritance.
  • Classes - Explains how to use classes in JavaScript for more modern inheritance.

Arrays

  • Array - The go-to reference for everything about arrays in JavaScript.
  • Array methods - A list of all the methods you can use on arrays.
  • Array guide - A helpful guide that explains arrays with visuals and examples.

Books

  • You Don't Know JS: this & Object Prototypes - A book that goes deep into JavaScript prototypes.
  • Eloquent JavaScript - Includes a great chapter on arrays.

These resources will help you understand more about array methods, how to use subclasses for adding your own features, what to consider for performance, and give you a deeper insight into how prototypes and inheritance work in JavaScript.

Here are some common questions about prototype array methods:

What is the difference between mutator and accessor methods?

Mutator methods change the original array, like adding or removing items. Accessor methods give you new information or a new array without changing the original.

For instance:

  • push() and pop() change the original array by adding or removing items.
  • map() and filter() give you a new array based on the original, without changing it.

When should I add methods to Array.prototype?

It's usually best to not add methods to Array.prototype to avoid slowing things down and causing problems with new JavaScript updates.

Instead, consider using array subclasses or separate functions for extra capabilities. This way, you don't change all arrays everywhere.

How do I chain array methods together?

The .with() method from ES2023 makes chaining straightforward:

[1, 2, 3].with().reverse().map(x => x * 2)

Without .with(), you can still chain by calling methods one after another:

[1, 2, 3]
  .filter(x => x > 1)
  .map(x => x * 2)

What is the difference between forEach() and map()?

  • forEach() goes over an array and is used for actions like logging or making API calls. It doesn't return anything.

  • map() goes over an array and returns a new array based on what you specify in the function. It's for transforming data.

When should I use arrow functions with arrays?

Arrow functions are great with array methods like .map() and .filter() because:

  • They're shorter.
  • They automatically bind this so you don't have to.
  • They're good for simple functions that return a value right away.

How can I improve performance with array methods?

  • Prefer using accessor methods like map() and filter() over mutators like push() or pop(). Accessors can be optimized more easily.

  • Turn common actions into functions you can reuse, instead of making new functions every time.

  • Use array methods instead of old loops like for or while for better performance. JavaScript engines are really good at optimizing these methods.

Here are some easy-to-read articles about using array methods in JavaScript:

These articles offer helpful tips on working with arrays, suggest different ways to approach problems, and give advice on what to watch out for, making it easier for you to use array methods in your projects.

Related posts

Why not level up your reading with

Stay up-to-date with the latest developer news every time you open a new tab.

Read more