Recently, I have been working on a big back-end management project. The front-end requires a lot of complex data processing, and I found many details that had been neglected before. In this special sorting out, I hope not familiar friends can bypass these pits I step on. The purpose of this article is to help you sort out some of the important and error-prone aspects of array manipulation. I hope it will also help and remind you. I will try to write humorous things to deepen your memory. Level is limited, really infinite. Hope you enjoy it, this article is very basic very basic, please detour, thank you… I don’t know why it’s trending…

First, common method analysis

ForEach (), map(), filter(), etc.

1, forEach

1.1 basis points

ForEach is frequently used to change the array itself and calculate the statistics of each element. Its important features are as follows:

  1. You can change the array itself, no return value;
  2. Instead of breaking out of the loop with a normal operation, try/catch can be used, but this is not recommended.

1.2 easy to fault point

  1. ForEach () doesn’t have to change its array. We can see if the elements in an array are both value types and reference types:
var arr1 = [
   {name:'naruto',age:16},
   {name:'sasuke',age:17} ]; Var arr2 = [1, 2, 3]; arr1.forEach(item => { item.age = item.age + 1} ); //=> [{name:'naruto',age:17},{name:'sasuke', the age: 18}] arr2 forEach (item = > {item = item * 2}) / / = > [1, 2, 3]Copy the code

As a result, ARR1 has changed, naruto and Sasuke have both grown a year, and ARR2 has not changed at all. So it’s a rude conclusion: forEach never changes an array when its elements are value types; When it is a reference type, you can change the array

  1. Chaining operations are not supported, so the following code is incorrect:
[1,2,3,4,5].foreach (item => console.log(item)).filter(item => {return item > 2 
})
// Uncaught TypeError: Cannot read property 'filter' of undefined
Copy the code

ForEach () does not support chained calls. Before calling forEach, you can do whatever you want with the array.

[1,2,3,4,5]. Filter (item => {return item > 2 
}).forEach(item => {
   console.log(item) 
})
Copy the code
  1. No copies of arrays will be created before iteration, this usage scenario is too small to ignore…

2, the map

Map () is very powerful, and it addresses many of the limitations of forEach(). A map is a map, where the original array is mapped to the new array.

2.1 basis points

  1. To create a new array, you need to have host objects, which means that the original array will not change after it is called;
  2. Each element in the array calls one of the provided functions and returns the result.

2.2 easy to fault point

  1. Creating a new array doesn’t mean you can’t use it to alter the existing array. You can just use the existing array:
letArr = [1, 2, 3]; arr = arr.map(item => {return item * 2 })
Copy the code

Arr also changes, so it doesn’t take much work…

  1. If you want to filter an array, map() does not work:
letNewArr = [1,2,3,4,5]. Map (item => {if(item > 3) return item })
// => [undefined, undefined, undefined, 4, 5]
Copy the code

The final result is undefined, undefined, undefined, 4, 5. Don’t tell me you can make do with a simple fix, not life, not code!

3, the filter

As we all know, filter() does what map() can’t. Filter (), like map(), creates a new array, and the elements in the new array are all the filtered objects that meet the criteria. Here’s a quick example:

letNewArr = [1, 2, 3, 4, 5]. The filter (item = > {if(item > 3) returnItem}) // => [4,5]Copy the code

I believe that there is no easy mistake point, there are comments to point out that ~~~

4, the sort ()

Sort () is used to sort the elements of an array. The sorting order can be alphabetic or numeric and in ascending or descending order.

4.1 basis points

1. The default sort is alphabetically ascending (or, more accurately, according to string Unicode code points) :

[3,4,2,1,5].sort() => [1,2,3,4,5] ['Javascript'.'Vue'.'React'.'Node'.'Webpack'].sort(); / / = > ["Javascript"."Node"."React"."Vue"."Webpack"]
Copy the code

4.2 easy to fault point

  1. Unlike map(), filter(), etc., sort() directly alters the original array (important!). ;

  2. If you want to sort by any other criteria, you provide the comparison function compareFunction(a,b), and the array is sorted by the value returned from the call, i.e. a and B are the two elements to be compared:

  • If compareFunction(a,b) is less than 0, a precedes B;
  • If compareFunction(a, b) is equal to 0, the relative positions of a and B remain the same (not guaranteed);
  • If compareFunction(a, b) is greater than 0, b precedes A; Go straight to the example:
let Users = [
  {name:'naruto',age:16},
  {name:kakashi,age:28},
  {name:'Jilaiya',age:50},
  {name:'sasuke',age:17}
];
Users.sort((a,b)=> {
   returnA.age-b.agge}) // => Naruto, Sasuke, Kakashi, ZaiyaCopy the code

5, some ()

Some () is also a good way to check that something in an array meets the criteria.

5.1 basis points

  1. Returns true if one of these conditions is met, and no further execution is performed (so performance friendly!). .
var result = [
   {name:'naruto',age:16},
   {name:'sasuke',age:17}
].some(item => {
	returnitem.age > 16 }); = >true
Copy the code

5.2 easy to fault point

Some () and every() return Boolean values, and that’s it. Don’t think about……

6, every ()

If some () is “| |” judgment, that every () is the “&” judgment, which is used to test each item in the array are all meet the conditions, only satisfy the will return true. And it makes sense:

var result = [
   {name:'naruto',age:16},
   {name:'sasuke',age:17}
].every(item => {
	returnitem.age > 16 }); = >false
Copy the code

Other classical methods

In our daily work, there are many business requirements that cannot be met by the above method, such as the following three requirements:

  1. Reprocess an array.
  2. Determines if there is an element in the current array and returns that element.
  3. Determine if there is an element in the current array and remove it.

For requirement 1, I believe that when you see “de-weight”, you will definitely think of new Set(), which is also a common interview question. For requirement 2, when you see whether there is an element in the current array, you might say filter() is doing the dirty work. No, I don’t believe it. Let’s discuss it separately.

1. Array de-duplication (not as easy as you think)

1.1 Limitations of new Set()

New Set(); new Set(); new Set();

letTempArr = new Set (,2,3,3,4,4,5 [1]) / / = > {1, 2, 3, 4, 5} / / and existing element is added in: TempArr. Add (3) / / = > {1, 2, 3, 4, 5} tempArr. Add (6) / / = > {6}Copy the code

Well, great, be sure to note that new Set() converts the result to an object! We rarely work with arrays whose elements are of value type, so let’s see if the elements are of reference type:

letmySet = new Set(); mySet.add(1); // Set(1) {1} mySet.add(5); // Set(2) {1, 5} mySet.add(5); // Set(2) {1, 5} myset.add ('some text'); MySet [...] / / = > [1, 5,'some text']

mySet.add({name:'jay Chou',age:40});
mySet.add({name:'jay Chou',age:40}); MySet [...] / / = > [1, 5,'some text',{name:'jay Chou',age:40},{name:'jay Chou',age:40}]
Copy the code

As you can see, Set() does not remove arrays of objects whose heavy elements are references. So what’s next?

1.2 _. UniqWith ()

Don’t worry, Lodash helps us out. Lodash is a consistent, modular, high-performance JavaScript utility library. It provides a nice method — _.uniqwith () :

import _ from 'lodash';
<script>
var objects = [{ 'x': 1, 'y': 2}, {'x': 2.'y': 1}, {'x': 1, 'y': 2}]; _.uniqWith(objects, _.isEqual); </script> //=> [{'x': 1, 'y': 2}, {'x': 2.'y': 1}]Copy the code

Where, _. IsEqual (value,other) is used to perform a deep comparison to determine whether the two values are equal. _. UniqWith () do reprocessing.

2. Get the specified element in the array

Another common scenario at work is to find the one I want in the array and return it to me. () already can’t do that, ok, it will only tell me whether there is any, the filter () really can do it, but if I know the array itself even if I think that, must have only one, not likely to be more, so, for reasons of performance, I don’t want to use the filter () to me from the beginning through to the end, so how to do?

2.1 findIndex ()

Ok, filter() does not support interrupt traversal, so we need to find a method that can interrupt traversal, we can use for… Of, this method supports interrupt traversal, but this method has a large amount of code, it is not recommended to use, interested students can check it. For this scenario, we can use findIndex() to get the index of the element we want. Once we get the index, we can kill as much as we want

let testArr = [{name:'naruto',age:16},{name:'sasuke',age:17},{name:kakashi,age:26}]
let index = testArr.findIndex(item => { returnitem.age > 16 }); / / = > 1Copy the code

Alternatively, you can use the _.findIndex() provided by Lodash to get the index directly from the object attribute value:

let testArr = [{name:'naruto',age:16},{name:'sasuke',age:17},{name:kakashi,age:26}]
let index = _.findIndex(testArr, {name:'sasuke'}); / / = > 1Copy the code

Note: The findIndex() method is not supported in IE 11 and earlier. So, if browser compatibility is required, use Lodash’s _.findIndex()

2.2 the find ()

Find (), as the name implies, is used to find the desired element in an array and, like some(), returns the element as long as there is one, without redundant traversal, which is performance-friendly.

let testArr = [{name:'naruto',age:16},{name:'sasuke',age:17},{name:kakashi,age:27},{name:'sasuke',age:17}]
let result = testArr.find(item => { return item.name == 'sasuke'});
// => { name:'sasuke',age:17 }
Copy the code

But! Unfortunately, IE 11 and earlier also don’t support find().

In the actual work, the array of various operations must be accomplished skilled, skilled, skilled again, I hope that I sorted out these problems can have a harvest for you. Ok, so much, the back of other problems and then add, I hope you like! Thanks for your likes!