Efficient use of array methods in javascript

Original author: pacdiv
  • Transfer
The author of the material, the translation of which we publish today, says that in the past few months, when checking pull requests, he always came across the same four flaws associated with the irrational use of array methods in JavaScript. In order for such flaws in the code, which had previously appeared in his programs, become less, he wrote this article.



Replacing indexOf () with includes ()


"If you are looking for something in an array, use the method indexOf()." Something like this recommendation I met on one of the courses when I was learning JavaScript. The recommendation is quite normal, nothing bad can be said about it.

On MDN, you can find out that the method indexOf()returns the first index by which an element can be found in the array. This means that if we plan to use this index in the program, the method is indexof()excellent for searching elements in arrays.

But what if we just need to find out if there is a certain element in the array or not? That is, we are not interested in the index of this element, if it is in the array, but in the fact of its presence or absence. With this approach, we are quite satisfied with the team that returns trueorfalse. In such cases, I recommend using not a method indexOf(), but a method includes()that returns a logical value. Consider an example:

'use strict';
const characters = [
  'ironman',
  'black_widow',
  'hulk',
  'captain_america',
  'hulk',
  'thor',
];
console.log(characters.indexOf('hulk'));
// 2console.log(characters.indexOf('batman'));
// -1console.log(characters.includes('hulk'));
// trueconsole.log(characters.includes('batman'));
// false

Using the find () method instead of the filter () method


The method filter()is a very useful tool. It, on the basis of one array, creates another array containing the elements of the source array corresponding to the given condition. As can be understood from the name of this method, it is intended for filtering arrays, during which arrays are usually obtained that are shorter than the original ones.

What if we know that after filtering the array, only one element will remain? For example, this can happen when trying to filter the elements of an array based on some unique identifier. In such a situation, I would not advise using the methodfilter(), because the array that it forms will contain only one element. If we are interested in an array element with a unique value, then we are going to work with a single value, and to represent such a value, the array is not needed.

If we talk about the performance of the method filter(), it turns out that he, in order to form a list of the elements that correspond to the condition given when he called, will have to look through the entire array. Moreover, imagine that there are hundreds of elements in an array that satisfy a given condition. This will result in the resulting array being quite large.

In order to avoid such situations, I would advise using the methodfind(). When called, it is passed a callback describing a condition very similar to the one used with the method filter(), but the method find()returns only the first element corresponding to the condition. In this case, this method stops working immediately after it finds such an element. As a result, the entire array does not have to be viewed.

'use strict';
const characters = [
  { id: 1, name: 'ironman' },
  { id: 2, name: 'black_widow' },
  { id: 3, name: 'captain_america' },
  { id: 4, name: 'captain_america' },
];
functiongetCharacter(name) {
  returncharacter => character.name === name;
}
console.log(characters.filter(getCharacter('captain_america')));
// [//   { id: 3, name: 'captain_america' },//   { id: 4, name: 'captain_america' },// ]console.log(characters.find(getCharacter('captain_america')));
// { id: 3, name: 'captain_america' }

Replacing the find () Method with the Some () Method


I have to admit that the mistake that we will discuss now, I have committed many times. Then I was advised to look at MDN and see how to improve what I was doing irrationally. If in a nutshell, it is very similar to what we have just considered, speaking of the methods indexOf()and includes().

In the above case, we saw that the method find()takes a callback as an argument and returns an array element. Is it possible to call the method the find()most successful solution in the event that we need to find out whether the array contains some value or not? Perhaps not, since this method returns the value of an element of the array, rather than a logical value.

In a situation like this, I would recommend using the methodsome()which returns a boolean value.

'use strict';
const characters = [
  { id: 1, name: 'ironman', env: 'marvel' },
  { id: 2, name: 'black_widow', env: 'marvel' },
  { id: 3, name: 'wonder_woman', env: 'dc_comics' },
];
functionhasCharacterFrom(env) {
  returncharacter => character.env === env;
}
console.log(characters.find(hasCharacterFrom('marvel')));
// { id: 1, name: 'ironman', env: 'marvel' }console.log(characters.some(hasCharacterFrom('marvel')));
// true

Using the reduce () method instead of a combination of the filter () and map () methods


It is said that the method reduce()can not be attributed to the simple to understand. However, if what can be done with it is done in two steps, using methods filter()and map()chained, it seems that something in this approach is wrong.

I say that with this approach, the array has to be viewed twice. The first pass performed by the method filter()involves viewing the entire array and creating a new, filtered array. After the second pass, performed by the method map(), again, a new array is created, which contains the results of the transformation of the array elements obtained after the operation of the methodfilter(). As a result, in order to enter the finished array, two methods are used. Each method has its own callback, while in the course of performing such an operation using the method an filter()array is created, with which we can no longer work.

In order to reduce the load on the system created by using two methods and to improve the performance of programs, in such cases I would advise using the method reduce(). The result will be the same, and the code will turn out better. This method allows you to filter the elements of interest to us and add them to the battery. A battery can be a numeric variable that stores, say, the sum of the elements of an array, it can be an object, a string, or an array in which we can accumulate the elements we need.

In our case, since we are talking about using the method map(), I would advise using the reduce()array method as a battery. In the following example, we filter the elements of the array, which are objects, by the value of the field env, and perform their conversion.

'use strict';
const characters = [
  { name: 'ironman', env: 'marvel' },
  { name: 'black_widow', env: 'marvel' },
  { name: 'wonder_woman', env: 'dc_comics' },
];
console.log(
  characters
    .filter(character => character.env === 'marvel')
    .map(character => Object.assign({}, character, { alsoSeenIn: ['Avengers'] }))
);
// [
//   { name: 'ironman', env: 'marvel', alsoSeenIn: ['Avengers'] },
//   { name: 'black_widow', env: 'marvel', alsoSeenIn: ['Avengers'] }
// ]
console.log(
  characters
    .reduce((acc, character) => {
      returncharacter.env === 'marvel'
        ? acc.concat(Object.assign({}, character, { alsoSeenIn: ['Avengers'] }))
        : acc;
    }, [])
)
// [
//   { name: 'ironman', env: 'marvel', alsoSeenIn: ['Avengers'] },
//   { name: 'black_widow', env: 'marvel', alsoSeenIn: ['Avengers'] }
// ]

Results


In this material, we examined some approaches to the effective use of array methods in solving various problems. We believe that the ideas on which the recommendations given by the author of this article are based can help in improving the JS code in other situations.

Dear readers! Have you ever come across examples of the unsustainable use of JavaScript mechanisms?


Also popular now: