Categories
JavaScript Basics

Sorting JavaScript Arrays

Sorting arrays is a common operation that’s done in many apps. The sort method that comes with JavaScript arrays makes this easy. However, there are lots of intricacies when it comes to sorting arrays.

In this article, we’ll look at how to sort arrays with the sort method. Also, we’ll look at how to compare objects to order them in the way that we desire.

Basic Sorting

The most basic sorting operation is probably sorting numbers. With the sort method, we can do this easily. For example, if we have the following array:

let arr = [3, 4, 5, 2, 5, 8, 9];

Then we can sort is with the sort method as follows:

arr.sort();

The arr array is sorted in place, so we don’t have to assign it to a new variable.

After calling sort, we get that the array is:

[2, 3, 4, 5, 5, 8, 9]

We can see that the sorting is done by ordering numbers in ascending order.

Sorting number arrays in ascending order are the simplest cases. We didn’t have to modify the sort method’s default functionality to do this.

We can also sort strings by ascending Unicode code point order. The sort method will sort by the total code points of each string. The full list of code points for Unicode characters are listed at https://en.wikipedia.org/wiki/List_of_Unicode_characters.

For example, given the following array:

let strings = ['foo', 'bar', 'baz'];

We can call sort by writing:

strings.sort();

to sort in ascending total Unicode code points.

Copying an Array Before Sorting

As we can see, sort will sort the array it’s called on in place. We can avoid this by copying the array to a new array before sorting.

To do this, we can either use the slice method as follows:

let sortedStrings = strings.slice().sort();

Or more conveniently, we can use the spread operator to do the same thing:

let sortedStrings = [...strings].sort();

Sorting with Compare Functions

The sort method can take an optional callback function to let us compare the content of the array to let us sort it the way we want.

The callback function takes 2 arguments. The first one is the array entry that comes first, the second is the one that comes after the one in the first argument.

We compare them and then return a positive number, negative number, or 0 depending on our preference.

Given that we have 2 entries, a and b for the first and second parameter for the callback respectively, we return a negative number to make a come before b. To make b come before a we can return a positive number.

To keep their order unchanged with respect to each other, we return 0.

For example, we can use this to sort numbers in reverse as follows:

arr.sort((a, b) => b - a);

We want to make the bigger entry come before the smaller entry, so we return b — a to make b come before a if b is bigger than a since b bigger than a means that b — a will be positive.

Otherwise, if b is smaller than a, it’ll be negative, and it’ll be zero if they’re the same.

It’s also handy for sorting by fields in an array of objects. If we want to sort by a field of objects, then we’ve to write a compare function to do it. For example, given the following array:

let arr = [{
    name: 'Joe',
    age: 20
  },
  {
    name: 'Mary',
    age: 16
  },
  {
    name: 'Jane',
    age: 22
  },
];

We can sort by the age field by ascending age as follows:

arr.sort((a, b) => a.age - b.age);

It works the same as sorting other numbers. If a.age is less than b.age , then we return a negative number, so a comes before b . If it’s the reverse, then b comes before a, where a and b are neighboring entries of the array.

Otherwise, if they’re the same, then a and b’s order stays the same.

Then we get the following if we log the array:

{name: "Mary", age: 16}
{name: "Joe", age: 20}
{name: "Jane", age: 22}

We can use the comparison operators like >, <, <=, or >=to compare strings.

For example, if we want to sort the array above by name, we can write:

arr.sort((a, b) => {
  if (a.name.toLowerCase() < b.name.toLowerCase()) {
    return -1;
  } else if (a.name.toLowerCase() > b.name.toLowerCase()) {
    return 1;
  }
  return 0;
});

Then we get the following result:

{name: "Jane", age: 22}
{name: "Joe", age: 20}
{name: "Mary", age: 16}

Comparing Non-English Strings

The callback for sorting strings above works great sorting English strings. However, it doesn’t work very well for non-English strings since it doesn’t take into account things like punctuation or accents.

To compare these kinds of strings, we can use the localeCompare method that comes with strings.

It has lots of optional that we can adjust for changing the comparison of strings, like whether to check accents, case, and other variants of a letter. The locale for comparison can also be adjusted.

The full list of options are at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare

We can use it as follows:

let arr = ['réservé', 'Premier', 'Cliché', 'communiqué', 'café', 'Adieu'];
arr.sort((a, b) => a.localeCompare(b, 'fr', {
  ignorePunctuation: true,
  sensitivity: 'base'
}));

In the code above, we passed a string b to compare with a in the comparison function of the localeCompare method as the first argument. Then we set the second argument to the 'fr' locale to indicate that we’re comparing French string. Finally, we passed in some basic options, which include ignoring punctuation and adjusting the sensitivity of the string comparison.

sensitivity set to 'base' means that strings that differ in letters are unequal.

After the sort method call above, we get that the value for arr is:

["Adieu", "café", "Cliché", "communiqué", "Premier", "réservé"]

Sorting JavaScript arrays have its tricky parts. The easiest case is sorting numbers and string code points in ascending order, which requires no comparison function.

For more complex comparisons, we’ve to pass in a comparison function. In it, returning a negative number will make the first value come before the second. Positive will make the second value come before the first. Returning 0 will keep the existing order.

Comparing non-English strings requires more care. We can use the localeCompare method that comes with strings to do the comparison by passing in various options.

Categories
JavaScript Basics

What Are Holes in Arrays?

One special feature of JavaScript arrays is that not every slot in the array has to be filled with values. This means that we can skip values as follows:

let arr = [];
arr[1] = 1;
arr[10] = 10;

We don’t have to worry about setting values for other slots of the array.

There’s also an alternative syntax for doing the above, by writing:

[, 1, , 2];

What we have above are called holes of an array, where we have nothing between the commas. An array with holes is called a sparse array.

In this piece, we’ll look at how holes in arrays are handled in JavaScript.


Checking for Values in Arrays

We can check for holes in arrays with the in operator. To do this, we can write something like the following code:

const arr = [, 1, , 2];
1 in arr;

We should get true returned from the last line since 1 is in the array.

ES6 treat holes in arrays as undefined entries. So if we want to check for holes in the array, check for undefined.

Iterators and generators also treat holes as undefined. For example, if we have

const arr = [, 1, , 2];
const iter = arr[Symbol.iterator]()

for (let a of iter) {
  console.log(a);
}

we get

undefined
1
undefined
2

If we call next to get the next item, as follows,

iter.next();

we get

{value: undefined, done: false}

for the first entry.

Likewise, if we have the given generator,

function* generator () {
  const arr = [, 1, , 2];
  for (let a of arr) {
    yield a;
  }
}

for (let a of generator()) {
  console.log(a);
}

we get the same thing.


Array.from()

Array.from() treats holes as undefined like with iterators and generators.

For example, if we have

const arr = [, 1, , 2];
const arrFrom = Array.from(arr);

then we get that the value of arrFrom is

[undefined, 1, undefined, 2]

Likewise, if we create an array from array-like objects, where we have non-negative integers as keys and a length property with a non-negative number as a value, missing entries are also treated as undefined.

For example, if we run

const arrFrom = Array.from({
  1: 'foo',
  length: 2
});

we get the value of arrFrom as

[undefined, "foo"]

How Array.prototype Methods Treat Holes

The behavior of these methods differs with different versions of JavaScript. In ES5, they’re the following:

  • forEach, filter, every, and some ignore holes.
  • map skips but preserves holes.
  • join and toString treat holes as if they were undefined elements but treat both null and undefined as empty strings.

The following is a full list of methods and how they deal with holes. Each method acts differently.

  • concat — keeps holes
  • copyWithin — holes are copied
  • entries, keys, values — treats holes as undefined
  • every — ignores holes
  • fill — fills holes
  • filter — removes holes
  • find — treats holes as elements
  • findIndex — treats holes as elements
  • forEach — ignores holes
  • indexOf — ignores holes
  • join — converts holes to empty strings
  • lastIndexOf — ignores holes
  • map — preserves holes
  • pop — treat holes as elements
  • push — preserves holes
  • reduce , reduceRight— ignores holes
  • reverse — preserves holes
  • shift — treat holes as undefined
  • slice — preserves holes
  • sort — preserves holes
  • toString — preserves holes
  • unshift — preserves holes
  • values — converts holes to undefined

When arrays are sparse, they have holes. They’re iterated through as undefined, but each array prototype method treats holes differently, so we have to be careful when defining arrays with holes and dealing with them.

We can use the in operator to check if a given entry is in an array.

Array.from() also treats holes as undefined and turns holes into undefined when converting arrays or array-like objects with holes into arrays.

Categories
JavaScript Basics

Truncating and Filling Entries: JavaScript Array Tips

JavaScript, like any other programming language, has many handy tricks that let us write our programs more easily. In this article, we will look at how to do different things that involve arrays, like truncating arrays, converting arrays to objects and filling arrays with data.

Truncating Arrays

In JavaScript, array objects have a length property that specifies the length of an array. It’s both a getter and setter property so in addition to being able to get the length of an array, we can also use it to set the length of an array.

Setting the length property to be less than the original length of the array will truncate the array up to the number of entries that we specify. For example, if we want to only keep the first entry of an array, then we can write something like:

let arr = [1, 2, 3, 4, 5, 6];
arr.length = 1
console.log(arr);

We simply set the length property of our array and then magically we get only the first element of the array left.

Alternatively, we can use the splice method to remove entries from an array. This method lets us removing, replace an existing element or adding new elements in place, but we only need it to delete elements from the array.

The argument of the splice method is the starting index start of which to start changing the array. It can be positive or negative. If it’s negative, then it’ll start changing the array from the end and move towards the start of the array. The end index is -1, the second is -2 and so on.

The second argument of the splice method is the deleteCount , which is an optional argument that lets us specify how many items to delete starting from the start parameter in the first element.

Subsequent arguments are the items that we want to insert into an array. This can go on for as long as we want. Only the first argument is required.

For example, if we want to truncate an array and keep only the first 2 elements, we can write something like the following code:

const arr = [1, 2, 3, 4, 5, 6];
arr.splice(2)
console.log(arr);

As we can see we only need to specify the first argument, and then the deleteCount will be automatically set so that it removes the entries on the right of the array. We can also specify a negative start index like in the following code:

const arr = [1, 2, 3, 4, 5, 6];
arr.splice(-1 * arr.length + 1)
console.log(arr);

So if we specify -1 * arr.length + n in the first argument, then we keep the first n entries of the original array.

We can also use the slice method to truncate arrays. It’s used for extracting values from an array in general and returns a new array with the extracted values. The slice method takes 2 arguments.

The first is an optional argument to specify where to begin extracting entries from an array. The second argument is another optional argument that specifies the end index of the original array to end the extraction of values from it. The value at the end index itself is excluded from the extraction.

For example, if we want the first 2 values from the original array, then we can write something like the following code:

let arr = [1, 2, 3, 4, 5, 6];
arr = arr.slice(0, 2);
console.log(arr);

When we run the code, we get back [1, 2] as the new value of arr . We can also specify negative indexes for the start and end. The last entry of the array is at -1, the second last element is at the index -2, and so on. So if we want to extract the first 2 elements of an array with negative indexes, we can write something like the following:

let arr = [1, 2, 3, 4, 5, 6];
arr = arr.slice(-1 * arr.length, -1 * arr.length + 2);
console.log(arr);

The first element of an array would be at index -1 * arr.length if we expressed it in terms of a negative index. Then the subsequent entries would be at -1 * arr.length + n where n is array entry at the n th position.

Filling Arrays with Data

With ES6 or later, we can fill arrays with an array with new data with the fill method. The fill method takes up to 3 arguments. The first is the value we want to add to the array.

The second optional argument is the start index of which we want to start filling data.

The default value of the second argument is 0. The third argument is an optional one that lets us specify the end index of to fill the array entry up to.

The default value for the third argument is the length of the array. Note that the end index itself is excluded from the filling so it won’t overflow when we call the fill method.

The fill the method returns a new array with the new values filled in. All existing values that were filled will replace any existing values that were in the original array.

For example, we can use it in the following way:

let arr = [1, 2, 3, 4, 5, 6];
arr = arr.fill(8)
console.log(arr);

Then we get the following output from the console.log :

[8, 8, 8, 8, 8, 8]

We can also change the index of the fill method to specify the fill boundary. For example, we can write:

let arr = [1, 2, 3, 4, 5, 6];
arr = arr.fill(8, 3, 5)
console.log(arr);

Then we get:

[1, 2, 3, 8, 8, 6]

from the console.log . If we specify an end index that’s over the length of the original array, then it’ll replace the values up to the original array up to the last position of the original array. For example, if we have:

let arr = [1, 2, 3, 4, 5, 6];
arr = arr.fill(8, 3, 10)
console.log(arr);

Then we get:

[1, 2, 3, 8, 8, 8]

We can also use negative indexes to specify the fill boundary with the fill method. The last position of the array would be -1, the second last would be -2, and so on. So we can call fill with negative indexes like the following:

let arr = [1, 2, 3, 4, 5, 6];
arr = arr.fill(8, -4, -1)
console.log(arr);

Then we get:

[1, 2, 8, 8, 8, 6]

since the third argument doesn’t include the last index. If we want to fill the last element as well with the new value, then we just omit the last argument like in the following code:

let arr = [1, 2, 3, 4, 5, 6];
arr = arr.fill(8, -4)
console.log(arr);

We get [1, 2, 8, 8, 8, 8] when we run the code above. If the second argument’s value is bigger than the third argument, then no fill operation will take place and the original array is returned. For example, if we have:

let arr = [1, 2, 3, 4, 5, 6];
arr = arr.fill(8, 4, 1)
console.log(arr);

Then we get back [1, 2, 3, 4, 5, 6] which is the original array.

Conclusion

In JavaScript, array objects have a length property that specifies the length of an array. It’s both a getter and setter property so in addition to being able to get the length of an array, we can also use it to set the length of an array. This means that setting the length property to be less than the original length of the array. We can also use the splice and slice methods to truncate arrays.

With ES6 or later, we can fill arrays with an array with new data with the fill method. The fill method takes up to 3 arguments. The first is the value we want to add to the array. The second optional argument is the start index of which we want to start filling data.

The default value of the second argument is 0. The third argument is an optional one that lets us specify the end index to fill the array entry up to. The default value for the third argument is the length of the array.

We can also use a negative index for the second and third arguments for setting the boundaries.

Categories
JavaScript Basics

Removing Duplicates and Emptying Arrays: JavaScript Array Tips

JavaScript, like any other programming language, has many handy tricks that let us write our programs more easily. In this article, we will look at how to do different things that involve arrays, like removing duplicates in an array and emptying an array.

Removing Duplicates in an Array

Using Sets

Removing duplicate entries from an array is a problem that we often have to solve there’re a few ways to do it. With ES6 or later, one of the easiest ways to do it is to convert it to a Set and then convert it back to an array.

We can convert an array to a Set by using the Set constructor. The constructor takes one argument, which is any iterable object. This means we can pass in an array, or other array-like objects like the arguments object, strings, NodeLists, TypedArrays like Uinit8Array, Map, other Sets and any other object that have a Symbol.iterator method.

We can also pass in null , which makes an empty set. Then we convert the set back to an array with the spread operator. For example, if we have an array, we can write the following code to convert it to a Set and back to an array to remove duplicate entries:

let arr = [1, 1, 2, 2, 3, 4, 5, 5, 6, 6];
arr = [...new Set(arr)];
console.log(arr);

In the code above, we started off with arr having duplicate entries and at the end, we should have the following logged:

[1, 2, 3, 4, 5, 6]

Note that we use let in our declaration of our array. We need to use let so that we can assign the new array in the second back to our arr variable. The first occurrence of each entry is kept and the other repeat occurrences are discarded.

We can also use the Array.from method to convert a Set to an array. The first argument of the Array.from method is an array-like object, like the arguments object, strings, NodeLists, TypedArrays like Uinit8Array, Map, other Sets and any other object that has a Symbol.iterator method. This means that we can use it as an alternative to the spread operator inside an array-like in the following code:

let arr = [1, 1, 2, 2, 3, 4, 5, 5, 6, 6];
arr = Array.from(new Set(arr));
console.log(arr);

With the code above, we should get the same output as in the first example.

Using Array.filter Method

Another alternative way to remove duplicates from an array is to use an array’s filter method. The filter method lets us filter out array entries that already exists. It takes a callback function that has 2 parameters, the first one is an array entry and the second one is the index of the array that’s being iterated to by the filter method.

The filter method filter let us defined what we want to keep and return a new array with the entries kept. We can use it along with the indexOf method, which returns the first occurrence of an array entry.

The indexOf method takes in any object that we want to look up the index to. We can use it to filter out duplicate occurrences of array entries like in the following code:

let arr = [1, 1, 2, 2, 3, 4, 5, 5, 6, 6];
arr = arr.filter((entry, index) => arr.indexOf(entry) === index);
console.log(arr);

The callback function in the filter returns the condition of the array items that we want to keep. In the code above, we want to return arr.indexOf(entry) === index since we want to return the first occurrence of each entry only. arr.indexOf(entry) returns the index of the first occurrence of an entry and the index is the array entry that we want to check against as the filter method is iterating through it.

The first iteration of the filter method should have entry being 1 and index being 0, so we get:

arr.indexOf(1) === 0

which evaluates to true since indexOf gets the index of the first entry so it returns 0, so the filter method will keep it. In the next iteration, we have entry being 1 again and index being 1, so we get:

arr.indexOf(1) === 1

We already know that arr.indexOf(1) is 0 but the right side is 1. This means the expression will be evaluated to false , so the filter method will discard it. For the third entry, we have entry having the value 2, and index being 2. Then we get:

arr.indexOf(2) === 2

arr.indexOf(2) will return 2 since the first occurrence of 2 is 2, and we have 2 on the right side since index is 2, so the expression evaluates to true , so it’ll be kept in the returned array. This goes on until all the entries are iterated through and checked. Therefore, we should get the same entries as the other examples above.

Using Array.reduce Method

A third way to remove duplicate entries from an array is to use the reduce method. The method combines the entries of an array into one entity according to what we specify in the callback function that we pass in and returns the combined entity.

The reduce method takes in a function that has 2 parameters, the first parameter has array that entries that have the entries that were combined so far by the reduce method, and the second parameter has the entry that is to be combined into the first value in the first parameter.

The second argument is the initial value that the first parameter of the callback function will take on. For example, we can use it to filter out duplicate arrays like in the following code:

let arr = [1, 1, 2, 2, 3, 4, 5, 5, 6, 6];
arr = arr.reduce((noDupArr, entry) => {
  if (noDupArr.includes(entry)) {
    return noDupArr;
  } else {
    return [...noDupArr, entry];
  }
}, [])
console.log(arr);

In the code above, we pass in a callback function that checks if the noDupArr , which is an array without any duplicate values, includes the entry in the second parameter by using the includes method that comes with arrays. The includes method takes in any object and lets us check if it’s already inside noDupArr . Therefore, if noDupArr.includes(entry) is true , then we return whatever has been combined so far. Otherwise, if the value hasn’t been included in the array already, then we can append the entry , by using the spread operator to spread the existing entries of noDupArr into a new array, then we add entry as the last entry of the array.

With this logic, the subsequent occurrences of values after the first value won’t be included in the newly combined array. Therefore, we won’t have duplicate entries included in the array. Initially, noDupArr will be an entry as specified by the second argument of the reduce method.

Empty an Array

There are a few ways to empty an array. We can either set it to an empty array or set the array’s length to 0. For example, we can set it to an empty array like in the following code:

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

The code above is the most obvious way to do it. A less known way to empty an array is to set its length to 0, as we do below:

let arr = [1, 1, 2, 2, 3, 4, 5, 5, 6, 6];
arr.length = 0;
console.log(arr);

Then we should also get an empty array for arr .

Conclusion

There’re many ways to remove duplicate entries from an array, each leaving the first occurrence of a value intact and discard the subsequent occurrences. We can convert it to a Set and then back to an array with the spread operator.

Also, we can use the filter and indexOf methods to return a new array with only the first occurrence of a value kept since indexOf returns the first occurrence of a value and the second parameter of the callback function that we pass into filter if the index of the original array that we can check against.

We can use the reduce and includes method together to do something similar to the filter and indexOf methods.

To empty arrays, we can set its length to 0 or set it to an empty array directly.

Categories
JavaScript Basics

Handy JavaScript Array Tips

JavaScript, like any other programming language, has many handy tricks that let us write our programs more easily. In this article, we will look at how to do different things that involve arrays, like checking if an object is an array and combining arrays.

Check if an object is an Array

There are multiple ways to check if a JavaScript object or primitive value is an array. The newest way to check is to use the Array.isArray method. It takes one argument, which is any object or primitive value that we want to check if it’s an array. It returns true if it’s an array and false otherwise. However, for TypedArray objects like Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array, BigInt64Array, and BigUint64Array . It always returns false . For example, if we write the following code:

console.log(Array.isArray([1, 2, 3]));
console.log(Array.isArray(0));
console.log(Array.isArray(null));
console.log(Array.isArray({
  a: 1
}));
console.log(Array.isArray(undefined));
console.log(Array.isArray(Infinity));
console.log(Array.isArray(new Uint8Array()));

We get the following output from the console.log statements:

true
false
false
false
false
false
false

It’s a very handy method for determining if an object is an array. An alternative way to check if an object is an array is to use the instanceof operator. It works by checking if Array.prototype is on an object’s prototype chain. The only situation that it fails but works when using Array.isArray is that instanceof will fail when checking objects across frames wince the object instance will likely be different from the one that’s used for the array test with the instanceof operator. We can use it as in the following code:

console.log([1, 2, 3] instanceof Array);
console.log(0 instanceof Array);
console.log(null instanceof Array);
console.log({
    a: 1
  }
  instanceof Array);
console.log(undefined instanceof Array);
console.log(Infinity instanceof Array);
console.log(new Uint8Array() instanceof Array);

The console.log output should be exactly the same as the ones before since we didn’t put any objects inside a frame. Array.isArray is the simplest and most robust solution since most modern browsers have this method built-in, and that it works across frames.

Combining Arrays

With modern JavaScript, combining arrays into one is easier than ever. Array objects have the concat method which is called on an array, and takes in one or more arguments, which one or more arrays or objects that we want to combine into the array which it’s being called on. Note that it can also take in other non-array values that we want to pass in to be added into the array that it’s being called on. It returns a new array instance with the new array values so that we chain a series of calls to the concat method to combine more arrays into one. For example, we can write the following code for the most basic use case:

const arr1 = [1, 2, 3];
const arr2 = ['a', 'b', 'c'];
const combinedArr = arr1.concat(arr2);
console.log(combinedArr);

Then we get that the value of combinedArr will be [1, 2, 3, “a”, “b”, “c”] . We can also pass in more than one argument each of which are arrays into the concat method like in the following code:

const arr1 = [1, 2, 3];
const arr2 = ['a', 'b', 'c'];
const arr3 = ['1', '2', '3'];
const arr4 = ['d', 'e', 'f'];
const arr5 = ['g', 'h', 'i'];
const arr6 = [null, Infinity, NaN];
const arr7 = [10, 11, 12];
const arr8 = [{}, {
  a: 1
}, {
  b: 2
}];
const combinedArr = arr1.concat(arr2, arr3, arr4, arr5, arr6, arr7, arr8);
console.log(combinedArr);

Then we get the following output from the console.log output:

[
  1,
  2,
  3,
  "a",
  "b",
  "c",
  "1",
  "2",
  "3",
  "d",
  "e",
  "f",
  "g",
  "h",
  "i",
  null,
  null,
  null,
  10,
  11,
  12,
  {},
  {
    "a": 1
  },
  {
    "b": 2
  }
]

As we can see, the concat method is smart enough to combine multiple arrays into the first array, and that we have all the entries from all the arrays in one new array. The array returned from the concat method does not reference the original arrays. Also, it works with multiple types of data. It doesn’t matter what we pass in it, should still work. For example, if we have the following code:

const arr1 = [1, 2, 3];
const arr2 = ['a', 'b', 'c'];
const arr3 = ['1', '2', '3'];
const arr4 = ['d', 'e', 'f'];
const arr5 = ['g', 'h', 'i'];
const arr6 = [null, Infinity, NaN];
const arr7 = [10, 11, 12];
const arr8 = [{}, {
  a: 1
}, {
  b: 2
}];
const combinedArr = arr1.concat(arr2, arr3, arr4, arr5, arr6, arr7, arr8, 1, 'a', {
  c: 3
});

Then we get the following output if we run console.log on combinedArr :

[
  1,
  2,
  3,
  "a",
  "b",
  "c",
  "1",
  "2",
  "3",
  "d",
  "e",
  "f",
  "g",
  "h",
  "i",
  null,
  null,
  null,
  10,
  11,
  12,
  {},
  {
    "a": 1
  },
  {
    "b": 2
  },
  1,
  "a",
  {
    "c": 3
  }
]

This is very useful since don’t have to worry about the data types of the objects that we pass in or how many arguments we passed into the concat method. It takes as many arguments as we pass in. Since the concat method returns a new array with the values combined into one array, we can also chain the calls of the concat method to combine multiple things into a single array-like in the following code:

const arr1 = [1, 2, 3];
const arr2 = ['a', 'b', 'c'];
const arr3 = ['1', '2', '3'];
const arr4 = ['d', 'e', 'f'];
const arr5 = ['g', 'h', 'i'];
const arr6 = [null, Infinity, NaN];
const arr7 = [10, 11, 12];
const arr8 = [{}, {
  a: 1
}, {
  b: 2
}];
const combinedArr = arr1
  .concat(arr2)
  .concat(arr3)
  .concat(arr4)
  .concat(arr5)
  .concat(arr6)
  .concat(arr7)
  .concat(arr8)
  .concat(1)
  .concat('a', {
    c: 3
  });

Then we should get the following out when we run console.log on combinedArr :

[
  1,
  2,
  3,
  "a",
  "b",
  "c",
  "1",
  "2",
  "3",
  "d",
  "e",
  "f",
  "g",
  "h",
  "i",
  null,
  null,
  null,
  10,
  11,
  12,
  {},
  {
    "a": 1
  },
  {
    "b": 2
  },
  1,
  "a",
  {
    "c": 3
  }
]

With ES6, we have the spread operator, which we can use to combine arrays into one by spreading the values of the array into another array, and we can do that for all the arrays in one array separated by a comma after each array is spread. The spread also works with all array-like objects like arguments , Sets, Maps, or any object that has a Symbol.iterator method, which return a generator so that we can iterate through the items in the object with the for...of loop. To combine arrays and objects together into one array with the spread operator, we can write something like the following code:

const arr1 = [1, 2, 3];
const arr2 = ['a', 'b', 'c'];
const arr3 = ['1', '2', '3'];
const combinedArr = [...arr1, ...arr2, ...arr3];

Then we get:

[
  1,
  2,
  3,
  "a",
  "b",
  "c",
  "1",
  "2",
  "3"
]

when we run console.log on combinedArr . It also works with overlapping values across different arrays like the concat method does. For example, we can write the following code:

const arr1 = [1, 2, 3];
const arr2 = ['a', 'b', 'c'];
const arr3 = [1, '2', '3'];
const combinedArr = [...arr1, ...arr2, ...arr3];

and get that the value of combinedArr would be:

[
  1,
  2,
  3,
  "a",
  "b",
  "c",
  1,
  "2",
  "3"
]

As we can see, we have the value 1 in both arr1 and arr3 , but they both made it into combinedArr , which is good. We can also put objects into our new array that before, after or between the spread operations like in the following code:

const arr1 = [1, 2, 3];
const arr2 = ['a', 'b', 'c'];
const arr3 = [1, '2', '3'];
const combinedArr = ['c', ...arr1, 'c', ...arr2, 'c', ...arr3];

Then we get the following value for combinedArr :

[
  "c",
  1,
  2,
  3,
  "c",
  "a",
  "b",
  "c",
  "c",
  1,
  "2",
  "3"
]

This means that the feature of the concat method can easily be replicated by the spread operator, and we don’t have to pass in a long list of arguments or chain multiple calls of the concat method together to combine arrays and other types of objects into one array.

There are multiple ways to check if a JavaScript object or primitive value is an array. The newest way to check is to use the Array.isArray method, but we can also use the old instanceof operator to check if an object is an array. Array.isArray works across frames so it’s more robust than the instanceof operator. With modern JavaScript, combining arrays into one is easier than ever. Array objects have the concat method which is called on an array and takes in one or more arguments, which one or more arrays or objects that we want to combine into the array which it’s being called on. Note that it can also take in other non-array values that we want to pass in to be added into the array that it’s being called on. It returns a new array instance with all the combined values included in the new array.