Home >Web Front-end >JS Tutorial >Immutable Array Methods: Write Cleaner JavaScript Code

Immutable Array Methods: Write Cleaner JavaScript Code

Jennifer Aniston
Jennifer AnistonOriginal
2025-02-10 11:12:09328browse

Immutable Array Methods: Write Cleaner JavaScript Code

This article follows the JavaScript variable assignment and mutation guide, and discusses the problems and solutions brought by the mutated array method. Many JavaScript array methods directly modify the original array, which can easily lead to difficult-to-trace bugs in large applications. But not all methods are like this. Methods such as Array.prototype.slice(), Array.prototype.concat(), Array.prototype.map(), and Array.prototype.filter() will return a new array, and the original array remains the same. To avoid unexpected mutations, we can write our own immutable array methods that return new array objects instead of modifying the original array. This article will cover immutable versions of methods such as pop, push, shift, unshift, reverse, splice, and

. Using immutable array methods can write clearer and easier to maintain code to avoid bugs caused by side effects.

Array mutation in JavaScript

JavaScript arrays are objects and can therefore be modified. Many built-in array methods directly modify the array itself, which violates best practices in programming. The following example shows a potential problem:
<code class="language-javascript">const numbers = [1,2,3];
const countdown = numbers.reverse();</code>

numbers This code seems normal. We create an array called countdown and want to create an array called numbers containing numbers arranged in reverse order in the array. On the surface, it does work:

<code class="language-javascript">countdown // [3, 2, 1]</code>

But the reverse() method also modified the numbers array, which is not the result we want:

<code class="language-javascript">numbers // [3, 2, 1]</code>

What's worse is that both variables refer to the same array, so any subsequent changes to one of the arrays will affect the other. If we use the Array.prototype.push() method to add an element with a value of 0 to the end of the countdown array, the numbers array will also change the same way (because they all refer to the same array):

<code class="language-javascript">countdown.push(0)
countdown // [3, 2, 1, 0]
numbers // [3, 2, 1, 0]</code>

This side effect is easily overlooked in large applications and leads to difficult-to-track bugs.

Variable array method in JavaScript

In addition to reverse(), there are many other array methods that cause this mutation:

  • Array.prototype.pop()
  • Array.prototype.push()
  • Array.prototype.shift()
  • Array.prototype.unshift()
  • Array.prototype.reverse()
  • Array.prototype.sort()
  • Array.prototype.splice()

In contrast, some methods do not modify the original array, but return a new array:

  • Array.prototype.slice()
  • Array.prototype.concat()
  • Array.prototype.map()
  • Array.prototype.filter()

These methods return a new array based on the actions performed. For example, the map() method can be used to double all numbers in an array:

<code class="language-javascript">const numbers = [1,2,3];
const countdown = numbers.reverse();</code>

Now, if we check the numbers array, we can see that it is not affected by the method call:

<code class="language-javascript">countdown // [3, 2, 1]</code>

Why do some methods modify arrays, while others don't? There seems to be no clear reason for this, but the recently added methods tend to make it immutable. It may be difficult to remember which methods will modify the array and which methods will not modify the array.

Immutable array method: Fix mutation problem

We have determined that mutations can cause problems, and that many array methods will cause mutations. Let's see how to avoid using them. It is not difficult to write some functions that return new array objects instead of modifying the original array. These functions are our immutable array methods.

Because we won't modify Array.prototype, these functions always take the array itself as the first parameter.

pop

Let's start by writing a new pop function that returns a copy of the original array but does not contain the last item. Note that Array.prototype.pop() returns the value popped from the end of the array:

<code class="language-javascript">numbers // [3, 2, 1]</code>

This function uses Array.prototype.slice() to return a copy of the array, but removes the last item. The second parameter -1 means "stop slice, 1 position before the end". We can see how it works in the following example:

<code class="language-javascript">countdown.push(0)
countdown // [3, 2, 1, 0]
numbers // [3, 2, 1, 0]</code>

push

Next, let's create a push() function that will return a new array, but append a new element at the end:

<code class="language-javascript">const numbers = [1,2,3];
const evens = numbers.map(number => number * 2);</code>

This creates a copy of the array using the extension operator. It then adds the value provided as the second parameter to the end of the new array. Here is an example:

<code class="language-javascript">numbers // [1, 2, 3]</code>

shift and unshift

We can write alternatives to Array.prototype.shift() and Array.prototype.unshift() similarly:

<code class="language-javascript">const pop = array => array.slice(0,-1);</code>

For our shift() function, we just cut the first element from the array instead of the last element. This can be seen in the following example:

<code class="language-javascript">const food = ['?','?','?','?'];
pop(food) // ['?','?','?']</code>

Our unshift() method will return a new array and append a new value to the beginning of the array:

<code class="language-javascript">const push = (array, value) => [...array,value];</code>
The

Extended operator allows us to place values ​​in an array in any order. We just have to put the new value in front of the original copy of the array. We can see how it works in the following example:

<code class="language-javascript">const food = ['?','?','?','?'];
push(food,'?') // ['?','?','?','?','?']</code>

reverse

Now let's try to write an alternative to the Array.prototype.reverse() method. It will return a copy of the array arranged in reverse order, rather than modifying the original array:

<code class="language-javascript">const numbers = [1,2,3];
const countdown = numbers.reverse();</code>

This method still uses the Array.prototype.reverse() method, but applies to a copy of the original array we create using the extension operator. There is no problem modifying the object right after it is created, and that's what we do here. We can see how it works in the following example:

<code class="language-javascript">countdown // [3, 2, 1]</code>

splice

Lastly, let's deal with Array.prototype.splice(). This is a very general function, so we won't completely rewrite its functionality (although it's an interesting exercise). Instead, we will focus on two main uses of slice: deleting items from arrays and inserting items into arrays.

Delete array items

Let's start with a function that will return a new array, but delete an item at the given index:

<code class="language-javascript">numbers // [3, 2, 1]</code>

This uses Array.prototype.slice() to cut the array in half - both sides of the item we want to delete. The first slice returns a new array, copying elements of the original array until the index specified as the parameter's index. The second slice returns an array containing the elements we want to delete, all the way to the end of the original array. We then use the extension operator to put them all in a new array. We can check if this works by trying to delete the item with index 2 in the food array below:

<code class="language-javascript">countdown.push(0)
countdown // [3, 2, 1, 0]
numbers // [3, 2, 1, 0]</code>

Add array items

Finally, let's write a function that will return a new array and insert a new value at a specific index:

<code class="language-javascript">const numbers = [1,2,3];
const evens = numbers.map(number => number * 2);</code>

This is similar to the way the remove() function works. It creates two slices of the array, but this time includes the elements at the index provided. When we regroup the two slices together, we insert the value provided as the parameter between them. We can check if this works by trying to insert a cupcake emoji into the middle of our food array:

<code class="language-javascript">numbers // [1, 2, 3]</code>

Now we have an immutable set of array methods that do not modify the original array. You can save them in one place and use them in your project. You can namespace them by taking them as a single object method, or use them as is when needed. These methods should be sufficient for most array operations. If you need to do different things, remember the golden rule: first use the extension operator to create a copy of the original array. Then, immediately apply any variable method to this copy.

Conclusion

In this article, we examine how JavaScript makes life difficult by modifying an array method that modifies the original array as part of the language. We then wrote our own immutable array method to replace these functions.

What other array methods can you think of that can benefit from having an immutable version?

FAQs on Creating and Using Immutable Array Methods in JavaScript

What is the concept of invariance in JavaScript?

Invariance is a basic concept in programming, which refers to the state of an object that cannot be modified after it is created. In JavaScript, invariance is not enforced by default. However, it is a powerful concept that can help you write more predictable and easier to maintain code. It is especially useful in functional programming, where invariance prevents errors and complexity caused by changing states.

Why should I use immutable array methods in JavaScript?

Using immutable array methods in JavaScript can write clearer and easier to maintain code. Since these methods do not modify the original array, they can prevent side effects that may cause errors. This is especially important in large code bases or when dealing with complex data structures. The immutable method returns a new array, while the original array remains unchanged. This makes your code more predictable and easier to debug.

What are some examples of immutable array methods in JavaScript?

JavaScript provides some immutable array methods that do not change the original array. Some examples include map(), filter(), reduce(), and concat() methods. The map() method creates a new array containing the results of the function provided for each element in the array. The filter() method creates a new array containing all elements of the test implemented by the provided function. The reduce() method applies a function to each element in the accumulator and array to reduce it to a single output value. The concat() method is used to merge two or more arrays and return a new array.

How to make my array immutable in JavaScript?

JavaScript does not provide a built-in method to make arrays immutable. However, you can achieve invariance by using methods that do not change the original array (e.g. map(), filter(), reduce(), and concat()). Another approach is to use the Object.freeze() method, which prevents the addition of new properties to the object, prevents the removal of existing properties, and prevents the enumeration, configurability, or writability of existing properties.

What is the difference between mutable and immutable methods in JavaScript?

The main difference between mutable and immutable methods in JavaScript is how they handle the original array. A mutable method modifies the original array, while an immutable method does not. Instead, the immutable method returns a new array. This makes your code more predictable and easier to debug as it prevents side effects that can cause errors.

Can I use immutable arrays with other data types in JavaScript?

Yes, you can use immutable arrays with other data types in JavaScript. The concept of invariance applies to all data types, not just arrays. For example, you can use immutable methods with strings, numbers, objects, etc. This can help you write clearer and easier to maintain code.

Is there any performance impact using immutable array methods?

Using immutable array methods may have some performance impact, as they usually create a new array instead of modifying the original array. This can lead to increased memory usage, especially in large arrays. However, in most cases, the benefits of using immutable methods, such as clearer code and fewer bugs, outweigh the potential performance costs.

How to use reduce() method in JavaScript?

The reduce() method in JavaScript is an immutable method that applies a function to each element in the accumulator and array to reduce it to a single output value. Here is an example of how to use it:

<code class="language-javascript">const numbers = [1,2,3];
const countdown = numbers.reverse();</code>

In this example, the reduce() method calculates the sum of all elements in the array.

What is the concat() method in JavaScript?

The concat() method in JavaScript is used to merge two or more arrays. This method does not change the existing array, but returns a new array. Here is an example:

<code class="language-javascript">countdown // [3, 2, 1]</code>

In this example, the concat() method merges array1 and array2 into a new array array3.

How to use filter() method in JavaScript?

The filter() method in JavaScript creates a new array containing all elements of the test implemented by the provided function. Here is an example of how to use it:

<code class="language-javascript">numbers // [3, 2, 1]</code>

In this example, the filter() method creates a new array containing numbers greater than 3.

The above is the detailed content of Immutable Array Methods: Write Cleaner JavaScript Code. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn