JavaScript Array Methods, Under the Hood (Part 1/2)

In this article, I’ll be showing you how the JavaScript array methods of .map() , .includes() , .concat() , & .flat() work by accomplishing the same thing using for loops. Those of you efficient-minded people out there screaming at me that using for loops takes more time, looks clunkier, makes it harder for coworkers and/or managers to understand, etc. may have a point; however, you will gain a deeper understanding of array methods, as well as a deeper appreciation for the fact that they exist, once you finish reading. Anyway, to make you efficient-minded readers happy, let’s dive right into it. .map() This array method creates a new array from calling a function for every item in a given array. It calls the function only once for each element that is not empty. It doesn’t change the original array whatsoever. Let’s say we are doing work for a bank & we want to compile a list of all client names as they appear in the data structure. The most-efficient way to do this would be to use the .map() method, but let’s first take a look at how we could do this with a ‘for’ loop: const bankAccounts = [ { id: 1, name: "Susan", balance: 100.32, deposits: [150, 30, 221], withdrawals: [110, 70.68, 120], }, { id: 2, name: "Morgan", balance: 1100.0, deposits: [1100] }, { id: 3, name: "Joshua", balance: 18456.57, deposits: [4000, 5000, 6000, 9200, 256.57], withdrawals: [1500, 1400, 1500, 1500], }, { id: 4, name: "Candy", balance: 0.0 }, { id: 5, name: "Phil", balance: 18, deposits: [100, 18], withdrawals: [100] }, ]; // Loop through data structure, then use 'for' loop to access the name from each account & push it to acctNames array: function getAllClientNames(array) { let acctNames = []; for (let acct of array) { acctNames.push(acct.name); } return acctNames; } // Get all client names from bankAccounts: getAllClientNames(bankAccounts); // returns: ['Susan', 'Morgan', 'Joshua', 'Candy', 'Phil'] We must first create an empty array to which we will push the values we want to it. Then, we need to run a for loop through the given array, in this case bankAccounts, then push the name of the current account to it, then finally return it once the loop has finished running. Now, let’s see how this looks if we use the .map() method: // Destructure data structure's elements to make array of all account names: function getAllClientNames(array) { return array.map(function(acct) { return acct.name; }); } // Get all client names from bankAccounts: getAllClientNames(bankAccounts); // returns: ['Susan', 'Morgan', 'Joshua', 'Candy', 'Phil'] As you can see, using the array method requires fewer steps, reducing the chance that we’ll screw something up along the way. All we need to do here is apply the method to the given array, then call a function, which takes in a parameter by which we’d like to iterate through the array, then return the name from that parameter, which is a bank account in the bankAccounts array. .includes() This method can be called on an array to determine if it contains a given value, & returns either true or false . Let’s create a function that takes an array & a value as its parameters, & determines if the array contains the value: function doesArrayInclude(array, value) { let isIncluded = false for (let elem of array) { if (elem === value) { isIncluded = true; } } return isIncluded; // returns 'true' if any element in the array is strictly equal to the given value; otherwise, it returns 'false' } doesArrayInclude([1, 1, 2, 3, 5], 6); // returns: false doesArrayInclude([1, 1, 2, 3, 5], 3); // returns: true If we’re going to use a ‘for’ loop to check if the array includes the given value, it’s best to assign a variable, isIncluded, to a default value of false. Then, we can use a ‘for…of’ loop to check if each element in the array is equal to the given value. If so, the value of isIncluded becomes true; otherwise, it remains false. Then, we return this variable at the end of the function. Here’s how it looks if we use the .includes() method: function doesArrayInclude(array, value) { return array.includes(value); } doesArrayInclude([1, 1, 2, 3, 5], 6); // returns: false doesArrayInclude([1, 1, 2, 3, 5], 3); // returns: true .concat() This array method puts two or more arrays together into one array, which this method returns. It does not change any elements in either array. Let’s create a function that concatenates two arrays, using for loops: function concatArrays(arr1, arr2) { let concatenatedArray = []; for (let elem of arr1) { concatenatedArray.push(elem); } for (let elem of arr2) { concatenatedArray.push(elem); } return concatenatedArray; } concatArrays([0, 1, 2], [5, 6, 7]); // returns: [0, 1, 2, 5, 6, 7] Above, we first have to declare an empty array, concatenatedArray, to which we then push each element of the t

Jan 21, 2025 - 18:21
 0
JavaScript Array Methods, Under the Hood (Part 1/2)

In this article, I’ll be showing you how the JavaScript array methods of .map() , .includes() , .concat() , & .flat() work by accomplishing the same thing using for loops. Those of you efficient-minded people out there screaming at me that using for loops takes more time, looks clunkier, makes it harder for coworkers and/or managers to understand, etc. may have a point; however, you will gain a deeper understanding of array methods, as well as a deeper appreciation for the fact that they exist, once you finish reading. Anyway, to make you efficient-minded readers happy, let’s dive right into it.

.map()

This array method creates a new array from calling a function for every item in a given array. It calls the function only once for each element that is not empty. It doesn’t change the original array whatsoever.

Let’s say we are doing work for a bank & we want to compile a list of all client names as they appear in the data structure. The most-efficient way to do this would be to use the .map() method, but let’s first take a look at how we could do this with a ‘for’ loop:

const bankAccounts = [
  {
    id: 1,
    name: "Susan",
    balance: 100.32,
    deposits: [150, 30, 221],
    withdrawals: [110, 70.68, 120],
  },
  { id: 2, name: "Morgan", balance: 1100.0, deposits: [1100] },
  {
    id: 3,
    name: "Joshua",
    balance: 18456.57,
    deposits: [4000, 5000, 6000, 9200, 256.57],
    withdrawals: [1500, 1400, 1500, 1500],
  },
  { id: 4, name: "Candy", balance: 0.0 },
  { id: 5, name: "Phil", balance: 18, deposits: [100, 18], withdrawals: [100] },
];

// Loop through data structure, then use 'for' loop to access the name from each account & push it to acctNames array:
function getAllClientNames(array) {
  let acctNames = [];
  for (let acct of array) {
    acctNames.push(acct.name);
  }
  return acctNames;
}
// Get all client names from bankAccounts:
getAllClientNames(bankAccounts); // returns: ['Susan', 'Morgan', 'Joshua', 'Candy', 'Phil']

We must first create an empty array to which we will push the values we want to it. Then, we need to run a for loop through the given array, in this case bankAccounts, then push the name of the current account to it, then finally return it once the loop has finished running.

Now, let’s see how this looks if we use the .map() method:

// Destructure data structure's elements to make array of all account names:
function getAllClientNames(array) {
  return array.map(function(acct) {
    return acct.name;
  });
}
// Get all client names from bankAccounts:
getAllClientNames(bankAccounts); // returns: ['Susan', 'Morgan', 'Joshua', 'Candy', 'Phil']

As you can see, using the array method requires fewer steps, reducing the chance that we’ll screw something up along the way. All we need to do here is apply the method to the given array, then call a function, which takes in a parameter by which we’d like to iterate through the array, then return the name from that parameter, which is a bank account in the bankAccounts array.

.includes()

This method can be called on an array to determine if it contains a given value, & returns either true or false .

Let’s create a function that takes an array & a value as its parameters, & determines if the array contains the value:

function doesArrayInclude(array, value) {
  let isIncluded = false
  for (let elem of array) {
    if (elem === value) {
      isIncluded = true;
    }
  }
  return isIncluded; // returns 'true' if any element in the array is strictly equal to the given value; otherwise, it returns 'false'
}
doesArrayInclude([1, 1, 2, 3, 5], 6); // returns: false
doesArrayInclude([1, 1, 2, 3, 5], 3); // returns: true

If we’re going to use a ‘for’ loop to check if the array includes the given value, it’s best to assign a variable, isIncluded, to a default value of false. Then, we can use a ‘for…of’ loop to check if each element in the array is equal to the given value. If so, the value of isIncluded becomes true; otherwise, it remains false. Then, we return this variable at the end of the function.

Here’s how it looks if we use the .includes() method:

function doesArrayInclude(array, value) {
  return array.includes(value);
}
doesArrayInclude([1, 1, 2, 3, 5], 6); // returns: false
doesArrayInclude([1, 1, 2, 3, 5], 3); // returns: true

.concat()

This array method puts two or more arrays together into one array, which this method returns. It does not change any elements in either array.

Let’s create a function that concatenates two arrays, using for loops:

function concatArrays(arr1, arr2) {
  let concatenatedArray = [];
  for (let elem of arr1) {
    concatenatedArray.push(elem);
  }
  for (let elem of arr2) {
    concatenatedArray.push(elem);
  }
  return concatenatedArray;
}
concatArrays([0, 1, 2], [5, 6, 7]); // returns: [0, 1, 2, 5, 6, 7]

Above, we first have to declare an empty array, concatenatedArray, to which we then push each element of the two given arrays, using for loops. Then, we’ll need to return this array at the end, of course.

Now, with the .concat() method:

function concatArrays(arr1, arr2) {
  return arr1.concat(arr2);
}
concatArrays([0, 1, 2], [5, 6, 7]); // returns: [0, 1, 2, 5, 6, 7]

.flat()

When this method is called on an array, it extracts all elements in any nested arrays & puts them all into one, single array. This method takes a parameter, which specifies how deep the nested array should be flattened, so, for example, if there is an array, inside an array, inside an array, a parameter of ‘2’ should be passed for all values to appear as single elements in the flattened array, as . The default parameter is ‘1’. It can also be used to remove empty elements inside an array, such as empty spaces.

In this example, we’ll flatten one array one level deep, using ‘for’ loops & with the method:

// FLATTEN ARRAY AT ONE LEVEL DEEP:
// Flatten array with 'for' loop:
function flatArrays(array) {
  let flattenedArray = [];
  for (let elem of array) {
    if (Array.isArray(elem)) {
      for (let subElem of elem) {
        flattenedArray.push(subElem);
      }
    } else {
      flattenedArray.push(elem);
    }
  }
  return flattenedArray;
}
flatArrays([1, 2, 3, [4, [5, 6]], 10]; // returns: [1, 2, 3, 4, [5, 6], 10]

// Flatten array with .flat():
function flatArrays(array) {
  return array.flat();
}
flatArrays([1, 2, 3, [4, [5, 6]], 10]; // returns: [1, 2, 3, 4, [5, 6], 10]

When using for loops, we again need to define an empty array, flattenedArray, to which we will eventually push certain values. Then, we loop through the given array; if the element is itself an array, we loop through this one as well, pushing each value to flattenedArray. If the element in the first loop is not an array, we simply push it to flattenedArray. Using the .flat() method, we could simply call it on the given array & return the result of this method call.

Now, let’s flatten an array at two levels deep. As you can see, this is super fun to do with for loops…

// FLATTEN ARRAY AT TWO LEVELS DEEP:
// Flatten array with 'for' loop:
function flatArrays(array) {
  let flattenedArray = [];
  for (let elem of array) {
    if (Array.isArray(elem)) {
      for (let subElem of elem) {
        // Check if there's an array inside of a first-level array:
        if (Array.isArray(subElem)) {
          for (let subSubElem of subElem) {
            // If so, push elements in second-level array to flattenedArray:
            flattenedArray.push(subSubElem);
          }
        // If not, push elements in first-level array to flattenedArray:
        } else {
          flattenedArray.push(subElem);
        }
      }
    } else {
      flattenedArray.push(elem);
    }
  }
  return flattenedArray;
}
flatArrays([1, 2, 3, [4, [5, 6]], 10]; // returns: [1, 2, 3, 4, 5, 6, 10]

// Flatten array with .flat():
function flatArrays(array) {
  return array.flat(2);
}
flatArrays([1, 2, 3, [4, [5, 6]], 10]; // returns: [1, 2, 3, 4, 5, 6, 10]

As you can see, the code becomes convoluted very quickly if we use ‘for’ loops to flatten arrays at levels higher than one, as we’d need to add a nested loop for every level. However, if we use the .flat() method, all we need to do is pass in a number that corresponds to the number of levels we wish to flatten, as the method’s parameter.

If you wish to flatten a gigantic array that contains an unknown number of subarrays, you could pass in some astronomical, virtually infinite number, like 203,345,976,997 as the method’s parameter, & each item in the base array, as well as those in all subarrays, will be returned as individual elements in the new array, & any empty elements will not appear in this new array.

There you have it, some examples of how some common JS array methods would work if we use ‘for’ loops instead. As the title suggests, part two will be coming soon.

If you have any comments or questions, I’d be happy to respond. If you found this article helpful, feel free to leave a reaction or a nice comment. If you think others would find this useful, please share it with them.
Click here to read part two of this two-part series, where I show how further array methods would work with loops!

Thanks for reading!

Originally published to Medium for JavaScript in Plain English on January 28, 2023

What's Your Reaction?

like

dislike

love

funny

angry

sad

wow