📜 ⬆️ ⬇️

JavaScript Guide, Part 5: Arrays and Loops

Today, in the fifth part of the translation of the course on JavaScript, we will talk about arrays and cycles. Arrays are used to solve a variety of problems. Often work with arrays using loops.

→ Part 1: first program, language features, standards
→ Part 2: code style and program structure
→ Part 3: Variables, Data Types, Expressions, Objects
→ Part 4: Functions
→ Part 5: Arrays and Loops
→ Part 6: Exceptions, Semicolon, Pattern Literals
→ Part 7: strict mode, this keyword, events, modules, mathematical calculations
→ Part 8: ES6 feature overview
→ Part 9: Overview of ES7, ES8, and ES9 Capabilities



Arrays


Arrays, objects of type Array , develop along with the other mechanisms of the language. They are lists of numbered values.
')
The first element of the array has an index (key) of 0, this approach is used in many programming languages.

In this section, we will look at modern methods of working with arrays.

â–ŤInitialization of arrays


Here are some ways to initialize arrays.

 const a = [] const a = [1, 2, 3] const a = Array.of(1, 2, 3) const a = Array(6).fill(1) //   ,   6 ,  1 

In order to gain access to a separate element of an array, a structure consisting of square brackets containing the index of the array element is used. Elements of arrays can be both read and written.

 const a = [1, 2, 3] console.log(a) //[ 1, 2, 3 ] const first = a[0] console.log(first) //1 a[0] = 4 console.log(a) //[ 4, 2, 3 ] 

The Array constructor is not recommended for declaring arrays.

 const a = new Array() //  const a = new Array(1, 2, 3) //  

This method should be used only when declaring typed arrays .

â–ŤReceiving array length


In order to know the length of an array, you need to refer to its length property.

 const l = a.length 

â–Ť Checking the array using the every () method


The every() method of arrays can be used to organize the inspection of all their elements using some condition. If all the elements of the array match the condition, the function will return true ; otherwise, it will return false .

A function is passed to this method that takes the arguments currentValue (the current element of the array), index (the index of the current element of the array), and array (the array itself). It can also take the optional value used as this when executing the function passed to it.
For example, let us check whether the values ​​of all the elements of the array exceed the number 10.

 const a = [11, 12, 13] const b = [5, 6, 25] const test = el => el > 10 console.log(a.every(test)) //true console.log(b.every(test)) //false 

Here, in the test() function, we are only interested in the first argument passed to it, so we declare it, indicating only the parameter el , into which the corresponding value will fall.

â–Ťcheck array using some () method


This method is very similar to the every() method, but it returns true if at least one of the array elements satisfies the condition given by the function passed to it.

â–ŤCreate an array based on an existing array using the map () method


The map() method of arrays allows you to iterate over arrays, applying to each of their elements passed to this method a function that converts an element, and create new arrays from the obtained values. Here, for example, how to get a new array, which is the result of multiplying all the elements of the original array by 2.

 const a = [1, 2, 3] const double = el => el * 2 const doubleA = a.map(double) console.log(a) //[ 1, 2, 3 ] console.log(doubleA) //[ 2, 4, 6 ] 

Filter an array using the filter () method


The filter() method is similar to the map() method, but it allows you to create new arrays containing only those elements of the original arrays that satisfy the condition specified by the function passed to the filter() method.

Reduce Reduce () method


The reduce() method allows you to apply a given function to the battery and to each value of the array, reducing the array to a single value (this value can be either a primitive or an object type). This method takes the function that performs the conversion and the optional initial value of the battery. Consider an example.

 const a = [1, 2, 3, 4].reduce((accumulator, currentValue, currentIndex, array) => { return accumulator * currentValue }, 1) console.log(a) //24 // 1: 1 * 1 = 1 // 2: 1 * 2 = 2 // 3: 2 * 3 = 6 // 4: 6 * 4 = 24 

Here we are looking for the product of all the elements of the array described using the literal, specifying the initial value of accumulator 1.

â–ŤAssize an array using the forEach () method


The array method forEach() can be used to iterate over the values ​​of arrays and to perform on them some actions specified by the function passed to the method. For example, print one by one the elements of an array into the console.

 const a = [1, 2, 3] a.forEach(el => console.log(el)) //1 //2 //3 

If you need to stop or interrupt the cycle while iterating through an array, you will have to throw an exception when using forEach() . Therefore, if in the course of solving a certain problem, you may need to interrupt the cycle, it is best to choose some other way to iterate over the elements of the array.

â–ŤAssize an array using the for ... of operator


The for...of operator appeared in the ES6 standard. It allows iterating objects to be iterated (including arrays). Here's how to use it.

 const a = [1, 2, 3] for (let v of a) { console.log(v) } //1 //2 //3 

At each iteration of the loop, the next element of the array a falls into the variable v .

â–ŤAssize array using for operator


The for statement allows you to organize loops, which, in particular, can be used to iterate (or initialize) arrays, referring to their elements by index. Usually, the index of the next element is obtained using the loop counter.

 const a = [1, 2, 3] for (let i = 0; i < a.length; i += 1) { console.log(a[i]) } //1 //2 //3 

If, during the execution of the loop, you need to skip its iteration, you can use the continue command. For early termination of the cycle, you can use the break command. If in a loop, for example, located in a certain function, use the return command, the loop and the function will end, and the return value using return will go to where the function was called.

@ Method @@ iterator


This method appeared in the ES6 standard. It allows you to get the so-called "object iterator" - an object, which in this case allows you to organize the enumeration of array elements. An array iterator can be obtained by using a symbol (such symbols are called “well-known symbols”) Symbol.iterator . After receiving an iterator, you can access its next() method, which, each time it is called, returns a data structure containing the next element of the array.

 const a = [1, 2, 3] let it = a[Symbol.iterator]() console.log(it.next().value) //1 console.log(it.next().value) //2 console.log(it.next().value) //3 

If you call the next() method after the last element of the array is reached, it returns, as an element value, undefined . The object returned by the next() method contains the value and done properties. The done property is set to false until the last element of the array is reached. In our case, if it is called it.next() for the fourth time, it will return the object { value: undefined, done: true } , while for the three previous calls this object looked like { value: , done: false } .

The entries() array method returns an iterator that allows you to iterate over the key-value pairs of the array.

 const a = [1, 2, 3] let it = a.entries() console.log(it.next().value) //[0, 1] console.log(it.next().value) //[1, 2] console.log(it.next().value) //[2, 3] 

The keys() method allows you to iterate over the keys of an array.

 const a = [1, 2, 3] let it = a.keys() console.log(it.next().value) //0 console.log(it.next().value) //1 console.log(it.next().value) //2 

â–ŤAdding elements to the end of the array


To add elements to the end of the array, use the push() method.

 a.push(4) 

Adding elements to the beginning of the array


To add elements to the beginning of the array, use the unshift() method.

 a.unshift(0) a.unshift(-2, -1) 

â–ŤDeletion of array elements


You can remove an element from the end of an array, while returning this element at the same time, using the pop() method.

 a.pop() 

Similarly, using the shift() method, you can remove an element from the beginning of an array.

 a.shift() 

The same, but already indicating the position of the removal of elements and their number, is done using the splice() method.

 a.splice(0, 2) //    2     a.splice(3, 2) //    2 ,    3 

â–ŤDeleting array elements and inserting other elements instead


To use certain operations to remove certain elements of the array and insert other elements instead, use the splice() method already familiar to you.

For example, here we delete 3 elements of the array starting from index 2, after which we add two other elements to the same place:

 const a = [1, 2, 3, 4, 5, 6] a.splice(2, 3, 'a', 'b') console.log(a) //[ 1, 2, 'a', 'b', 6 ] 

â–ŤUniting multiple arrays


To combine multiple arrays, you can use the concat() method, which returns a new array.

 const a = [1, 2] const b = [3, 4] const c = a.concat(b) console.log(c) //[ 1, 2, 3, 4 ] 

â–Ť Search for elements in the array


The ES5 standard introduces the indexOf() method, which returns the index of the first occurrence of the required array element. If the element in the array cannot be found, it returns -1 .

 const a = [1, 2, 3, 4, 5, 6, 7, 5, 8] console.log(a.indexOf(5)) //4 console.log(a.indexOf(23)) //-1 

The lastIndexOf() method returns the index of the last occurrence of an element in an array, or, if no element is found, -1 .

 const a = [1, 2, 3, 4, 5, 6, 7, 5, 8] console.log(a.lastIndexOf(5)) //7 console.log(a.lastIndexOf(23)) //-1 

In ES6, the find() array method has appeared, which performs a search on an array using the function passed to it. If the function returns true , the method returns the value of the first element found. If the item cannot be found, the function will return undefined .

Its use can look like this.

 a.find(x => x.id === my_id) 

Here in the array containing the objects, an element is searched for, the property of which id equals the given one.

The findIndex() method is similar to find() , but it returns the index of the item found or undefined .

In ES7, the includes() method has appeared, which allows you to check for the presence of a certain element in the array. It returns true or false by finding or not finding the item of interest to the programmer.

 a.includes(value) 

Using this method, you can check for the presence of a certain element not the entire array, but only a certain part of it, starting with the index specified when calling this method. The index is set using the second, optional, parameter of this method.

 a.includes(value, i) 

â–ŤGetting an array fragment


In order to get a copy of a certain fragment of an array as a new array, you can use the slice() method. If this method is called without arguments, then the returned array will be a full copy of the original one. It takes two optional parameters. The first one sets the initial index of the fragment, the second - the final one. If the final index is not specified, the array is copied from the specified starting index to the end.

 const a = [1, 2, 3, 4, 5, 6, 7, 8, 9] console.log(a.slice(4)) //[ 5, 6, 7, 8, 9 ] console.log(a.slice(3,7)) //[ 4, 5, 6, 7 ] 

â–Ť Array sorting


To organize the sorting of array elements in alphabetical order ( 0-9A-Za-z ), the sort() method is used without passing arguments to it.

 const a = [1, 2, 3, 10, 11] a.sort() console.log(a) //[ 1, 10, 11, 2, 3 ] const b = [1, 'a', 'Z', 3, 2, 11] b.sort() console.log(b) //[ 1, 11, 2, 3, 'Z', 'a' ] 

This method can be passed a function that sets the sort order. The function takes, for comparing the two elements, the parameters a and b . It returns a negative number if a less than b by some criterion, 0 if they are equal, and a positive number if a greater than b . When writing a similar function to sort numeric arrays, it can return the result of subtracting a and b . So, returning the result of evaluating the expression a - b means sorting the array in ascending order; returning the result of evaluating the expression b - a will result in sorting the array in descending order.

 const a = [1, 10, 3, 2, 11] console.log(a.sort((a, b) => a - b)) //[ 1, 2, 3, 10, 11 ] console.log(a.sort((a, b) => b - a)) //[ 11, 10, 3, 2, 1 ] 

In order to reverse the order of the elements of an array, you can use the reverse() method. It, like sort() , modifies the array for which it is called.

â–ŤGetting the string representation of the array


To get a string representation of an array, you can use its toString() method.

 a.toString() 

A similar result is given by the join() method, called without arguments.

 a.join() 

To him, as an argument, you can pass an element delimiter.

 const a = [1, 10, 3, 2, 11] console.log(a.toString()) //1,10,3,2,11 console.log(a.join()) //1,10,3,2,11 console.log(a.join(', ')) //1, 10, 3, 2, 11 

â–ŤCreate copies of arrays


To create a copy of the array by copying the values ​​of the original array into a new array, you can use the Array.from() method. It is also suitable for creating arrays from array-like objects (from strings, for example).

 const a = 'a string' const b = Array.from(a) console.log(b) //[ 'a', ' ', 's', 't', 'r', 'i', 'n', 'g' ] 

The Array.of() method can also be used to copy arrays, as well as to “build” arrays from various elements. For example, to copy the elements of one array to another, you can use the following construction.

 const a = [1, 10, 3, 2, 11] const b = Array.of(...a) console.log(b) // [ 1, 10, 3, 2, 11 ] 

To copy the elements of an array to a certain place of the array itself, use the copyWithin() method. Its first argument specifies the initial index of the target position, the second - the initial index of the position of the source of elements, and the third parameter, optional, specifies the final index of the position of the source of the elements. If you do not specify it, everything will be copied to the specified location in the array, starting from the initial index of the source position to the end of the array.

 const a = [1, 2, 3, 4, 5] a.copyWithin(0, 2) console.log(a) //[ 3, 4, 5, 4, 5 ] 

Cycles


Above, speaking of arrays, we have already come across some ways of organizing loops. However, cycles in JavaScript are not only used to work with arrays, but we have considered far from all of their types. Therefore, now we will take some time to consider different ways of organizing loops in JavaScript and talk about their features.

â–Ť for loop


Consider an example of the application of this cycle.

 const list = ['a', 'b', 'c'] for (let i = 0; i < list.length; i++) { console.log(list[i]) //,     console.log(i) // } 

As already mentioned, you can interrupt the execution of such a cycle using the break command, and you can skip the current iteration and proceed directly to the next using the continue command.

For Cycle forEach


We also discussed this cycle. Let us give an example of sorting an array with its help.

 const list = ['a', 'b', 'c'] list.forEach((item, index) => { console.log(item) // console.log(index) // }) //     ,      list.forEach(item => console.log(item)) 

Recall that in order to interrupt such a cycle, it is necessary to throw an exception, that is, if using a cycle it may be necessary to interrupt it, it is better to choose some other cycle.

â–Ť do ... while loop


This is the so-called “postcondition cycle”. Such a cycle will be executed at least once before checking the condition of completion of the cycle.

 const list = ['a', 'b', 'c'] let i = 0 do { console.log(list[i]) // console.log(i) // i = i + 1 } while (i < list.length) 

It can be interrupted using the break command, it is possible to proceed to its next iteration with the continue command.

While while loop


This is the so-called “precondition cycle”. If, at the entrance to the cycle, the condition of continuing the cycle is false, it will not be fulfilled even once.

 const list = ['a', 'b', 'c'] let i = 0 while (i < list.length) { console.log(list[i]) // console.log(i) // i = i + 1 } 

â–ŤCycle for ... in


This cycle allows you to iterate through all the enumerated properties of an object by their names.

 let object = {a: 1, b: 2, c: 'three'} for (let property in object) { console.log(property) //  console.log(object[property]) //  } 

â–ŤCycle for ... of


The for...of loop combines the convenience of the forEach loop and the ability to interrupt its work with regular means.

 //  for (const value of ['a', 'b', 'c']) { console.log(value) // } //       `entries()` for (const [index, value] of ['a', 'b', 'c'].entries()) { console.log(index) // console.log(value) // } 

Notice that here, in the loop header, the keyword const , and not, as you would expect, let . If the variables inside the loop block do not need to be reassigned, then const us.
If we compare the for...in and for...of loops, then it turns out that for...in iterates the property names, and for...of property values.

Cycles and scopes


One feature of JavaScript is associated with loops and with scopes of variables, which can give a developer some problems. In order to deal with these problems, let talk about cycles, scopes, and the var and let keywords.

Consider an example.

 const operations = [] for (var i = 0; i < 5; i++) { operations.push(() => {   console.log(i) }) } for (const operation of operations) { operation() } 

The loop performs 5 iterations, each of which adds a new function to the operations array. This function displays the value of the loop counter in the console - i . After the functions are added to the array, we search through this array and call the functions that are its elements.

By executing such a code, you can expect the result shown below.

 0 1 2 3 4 

But in fact, he displays the following.

 5 5 5 5 5 

Why is this so? The thing is that as a loop counter, we use a variable declared using the var keyword.

Since the declarations of such variables rise to the top of the scope, the above code is similar to the following.

 var i; const operations = [] for (i = 0; i < 5; i++) { operations.push(() => {   console.log(i) }) } for (const operation of operations) { operation() } 

As a result, it turns out that in the for...of loop, in which we iterate over the array, the variable i is still visible, it is equal to 5, as a result, referring to i in all functions, we derive the number 5.

How to change the behavior of the program so that it would do what is expected of it?

The simplest solution to this problem is to use the let keyword. It, as we said, appeared in ES6, its use allows you to get rid of some of the oddities characteristic of var .

In particular, in the example above, it is enough to change the var to let and everything will work as it should.

 const operations = [] for (let i = 0; i < 5; i++) { operations.push(() => {   console.log(i) }) } for (const operation of operations) { operation() } 

Now, at each iteration of the loop, each function added to the operations array gets its own copy of i . Remember that in this situation you cannot use the keyword const , since the value of i in the cycle changes.

Another way to solve this problem, which was often used before the emergence of the ES6 standard, when the keyword " let did not exist, is to use IIFE.

With this approach, the value of i stored in the closure, and the function returned by IIFE and having access to the closure gets into the array. This function can be performed when the need arises. Here's what it looks like.

 const operations = [] for (var i = 0; i < 5; i++) { operations.push(((j) => {   return () => console.log(j) })(i)) } for (const operation of operations) { operation() } 

Results


Today we talked about arrays and loops in javascript. The topic of our next material is exception handling, semicolon usage and pattern literals.

Dear readers! What methods for working with arrays in JavaScript do you use most often?

Source: https://habr.com/ru/post/430380/


All Articles