JavaScript Guide, Part 5: Arrays and Loops

https://medium.freecodecamp.org/the-complete-javascript-handbook-f26b2c71719c
  • Transfer
  • Tutorial
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 cycles
Part 6: exceptions, semicolon, template literals
Part 7: strict mode, this keyword, events, modules, mathematical calculations
Part 8: an overview of the features of the ES6 standard
Part 9: ES7, ES8 and ES9 features overview



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] = 4console.log(a) //[ 4, 2, 3 ]

Constructor Arrayfor declaring arrays is not recommended.

const a = newArray() //не рекомендуетсяconst a = newArray(1, 2, 3) //не рекомендуется

This method should be used only when declaring typed arrays .

▍Receiving array length


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

const l = a.length

▍ Checking the array using the every () method


The array method every()can be used to organize the inspection of all their elements using a certain 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 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 an optional value used in quality thiswhen 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 > 10console.log(a.every(test)) //trueconsole.log(b.every(test)) //false

Here, in the function test(), 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 method every(), but it returns trueif at least one of the elements of the array satisfies the condition given by the function passed to it.

▍Create an array based on an existing array using the map () method


The array method map()allows you to iterate through the arrays, applying to each element passed to this method a function that converts the element, and create new arrays from the values ​​obtained. 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 * 2const doubleA = a.map(double)
console.log(a) //[ 1, 2, 3 ]console.log(doubleA) //[ 2, 4, 6 ]

МассFilter an array using the filter () method


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

Reduce Reduce () method


The method reduce()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 certain 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 forEach()to throw an exception when using it . 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 operator for...ofappeared in the standard ES6. 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 vnext element of the array falls into the variable a.

▍Assize array using for operator


The operator forallows you to organize cycles, which, in particular, can be used to iterate (or initialize) arrays, referring to their elements by indices. 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 cycle, you need to skip its iteration, you can use the command continue. For early termination of the cycle, you can use the command break. If in a loop, for example, located in a certain function, to use a command return, the execution of the loop and the function will end, and the returnvalue returned with the help will get to where the function was called from.

@ 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 using a symbol (such symbols are called “known symbols”) Symbol.iterator. After receiving an iterator, you can refer to its method next(), 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) //1console.log(it.next().value) //2console.log(it.next().value) //3

If you call the method next()after the last element of the array is reached, he will return, as the value of the element undefined. The object returned by the method next()contains the properties valueand done. The property donetakes a value falseuntil the last element of the array is reached. In our case, if called it.next()for the fourth time, it will return the object { value: undefined, done: true }, while with the three previous calls this object looked like { value: значение, done: false }.

The array method entries()returns an iterator that allows you to iterate over the key-value pairs of an 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 method keys()allows you to iterate over the keys of the array.

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

▍Adding elements to the end of the array


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

a.push(4)

Adding elements to the beginning of the array


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

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

▍Deletion of array elements


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

a.pop()

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

a.shift()

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

a.splice(0, 2) // удаляет и возвращает 2 элемента из начала массива
a.splice(3, 2) // удаляет и возвращает 2 элемента, начиная с индекса 3

▍Deleting array elements and inserting other elements instead


In order to use one operation to remove certain elements of the array and insert other elements instead, the method already familiar to you is used splice().

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 several arrays, you can use the method concat()that 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


In the ES5 standard, a method appeared indexOf()that returns the index of the first occurrence of the desired element of the array. If the element in the array cannot be found, it is returned -1.

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

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

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

In ES6, the arrays method has appeared find(), 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, the search is carried out for an element whose property idequals the given one.

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

ES7 has a method includes()that allows you to check for the presence of a certain element in the array. It returns trueeither falseby 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 the array in the form of a new array, you can use the method slice(). 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 method is used sort()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 aand b. It returns a negative number if aless bby any criterion, 0 if they are equal, and a positive number if amore b. When writing a similar function to sort numeric arrays, it can return the result of subtracting aand b. So, returning the result of evaluating the expression a - bmeans sorting the array in ascending order; returning the result of evaluating the expression b - awill 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 the array, you can use the method reverse(). It, as well as 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 method toString().

a.toString()

A similar result is given by a method join()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,11console.log(a.join()) //1,10,3,2,11console.log(a.join(', ')) //1, 10, 3, 2, 11

▍Create copies of arrays


To create a copy of the array by copying to the new array the values ​​of the original array, you can use the method Array.from(). 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 method Array.of()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 in a certain place of the array itself, the method is used copyWithin(). 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, it is possible to interrupt the execution of such a cycle using a command break, and you can skip the current iteration and go directly to the next using the command continue.

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 = 0do {
  console.log(list[i]) //значение
  console.log(i) //индекс
  i = i + 1
} while (i < list.length)

It can be interrupted using the command break, you can go to its next iteration with the command continue.

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 = 0while (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 cycle for...ofcombines the convenience of the cycle forEachand the ability to interrupt its work by 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) //значение
}

Note that here, in the header cycle, the keyword const, and not, as one might expect let. If the variables inside the loop block do not need to be reassigned, then constwe are quite suitable.
If we compare the cycles for...inand for...of, it turns out that it for...inenumerates the names of properties, and the for...ofvalues ​​of properties.

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's talk about cycles, scopes, and keywords varand let.

Consider an example.

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

In the loop, 5 iterations are performed, at each of which a operationsnew function is added to the 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.

01234

But in fact, he displays the following.

55555

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

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 loop for...ofin which we iterate over the array, the variable iis still visible, it is equal to 5, as a result, referring to iall functions, we derive the number 5.

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

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

In particular, in the above example, it is enough to change varto letand 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 array operationsgets its own copy i. Remember that in this situation you cannot use a keyword const, as the value iin the cycle changes.

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

With this approach, the value is istored 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?


Also popular now: