📜 ⬆️ ⬇️

All ways to iterate an array in javascript

Content:




I. bust real arrays


At the moment there are three ways to iterate the elements of this array:
  1. Array.prototype.forEach method;
  2. classic for loop;
  3. “Correctly” constructed for...in loop.

In addition, in the near future, with the advent of the new standard ECMAScript 6 (ES 6), two more ways are expected:
  1. loop for...of (implicit use of an iterator);
  2. explicit use of an iterator.

1. The forEach method and related methods


If your project is designed to support the capabilities of the ECMAScript 5 (ES5) standard, you can use one of its innovations - the forEach method.

Usage example:
 var a = ["a", "b", "c"]; a.forEach(function(entry) { console.log(entry); }); 

In general, the use of forEach requires the connection of the es5-shim emulation library for browsers that do not have native support for this method. These include IE 8 and earlier, which are still used in some places.

The advantages of forEach include the fact that there is no need to declare local variables to store the index and the value of the current element of the array, since they are automatically passed to the callback function (callback) as arguments.
')
If you are worried about the possible costs of calling a callback for each item, do not worry and read this .

forEach designed to iterate through all the elements of an array, but apart from it, ES5 offers some more useful methods for iterating over all or some elements, plus performing some actions on them:

2. Cycle for


Good old for taxis :

 var a = ["a", "b", "c"]; var index; for (index = 0; index < a.length; ++index) { console.log(a[index]); } 

If the array length is unchanged during the whole cycle, and the cycle itself belongs to the critical in terms of performance code segment (which is unlikely), then you can use the “more optimal” version of for with storing the length of the array:

 var a = ["a", "b", "c"]; var index, len; for (index = 0, len = a.length; index < len; ++index) { console.log(a[index]); } 

Theoretically, this code should be executed a little faster than the previous one.

If the order of enumeration of elements is not important, then you can go even further in terms of optimization and get rid of the variable to store the length of the array by changing the order of enumeration to reverse:

 var a = ["a", "b", "c"]; var index; for (index = a.length - 1; index >= 0; --index) { console.log(a[index]); } 

However, in modern JavaScript engines, such optimized games usually mean nothing.

3. Proper use of the for ... in loop


If you are advised to use the for...in loop, remember that iterating over arrays is not what it is intended for . Contrary to the common misconception, the for...in loop loops through not the array indices, but enumerated properties of the object.

However, in some cases, such as iterating over sparse arrays , for...in may be useful, if only you follow the precautions, as shown in the example below:

 // a -   var a = []; a[0] = "a"; a[10] = "b"; a[10000] = "c"; for (var key in a) { if (a.hasOwnProperty(key) && /^0$|^[1-9]\d*$/.test(key) && key <= 4294967294) { console.log(a[key]); } } 

In this example, at each iteration of the loop, two checks are performed:
  1. that the array has its own property named key (not inherited from its prototype).
  2. that key is a string containing a decimal notation of an integer whose value is less than 4294967294 . Where does the last number come from? From the definition of the array index in ES5, from which it follows that the largest index that an element in an array can have: (2^32 - 2) = 4294967294 .

Of course, such checks will take extra time when performing a cycle. But in the case of a sparse array, this method is more efficient than the for loop, since in this case only those elements that are explicitly defined in the array are iterated. So, in the example above, only 3 iterations will be executed (for indices 0, 10 and 10000) - against 10001 in the for loop.

In order not to write such a cumbersome code of checks each time an array iteration is required, you can arrange it as a separate function:

 function arrayHasOwnIndex(array, key) { return array.hasOwnProperty(key) && /^0$|^[1-9]\d*$/.test(key) && key <= 4294967294; } 

Then the loop body from the example will be significantly reduced:

 for (key in a) { if (arrayHasOwnIndex(a, key)) { console.log(a[key]); } } 

The above code checks is universal, suitable for all cases. But instead, you can use a shorter version, although not formally correct, but nevertheless suitable for most cases:

 for (key in a) { if (a.hasOwnProperty(key) && String(parseInt(key, 10)) === key) { console.log(a[key]); } } 

4. The for ... of loop (implicit use of an iterator)


ES6, while still in draft status, must enter iterators into JavaScript.

An iterator is a protocol implemented by an object that defines a standard way to obtain a sequence of values ​​(finite or infinite).
An iterator is an object in which the next() method is defined - a function with no arguments, which returns an object with two properties:
  1. done ( boolean ) - true if the iterator has reached the end of the iterated sequence. Otherwise false .
  2. value - determines the value returned by the iterator. May not be defined (absent) if the done property is true .

Many built-in objects, incl. real arrays have iterators by default. The simplest way to use an iterator in real arrays is to use the new for...of construct.

An example of using for...of :

 var val; var a = ["a", "b", "c"]; for (val of a) { console.log(val); } 

In the example above, the for...of loop implicitly calls the Array object's iterator to get each value of the array.

5. Explicit use of an iterator


Iterators can also be used explicitly, though, in this case, the code becomes much more complicated compared to the for...of loop. It looks like this:

 var a = ["a", "b", "c"]; var it = a.entries(); var entry; while (!(entry = it.next()).done) { console.log(entry.value[1]); } 

In this example, the Array.prototype.entries method returns an iterator that is used to output the values ​​of the array. At each iteration, entry.value contains an array of the form [, ] .

Ii. Brute force objects


In addition to real arrays, javascript- like objects are also found in JavaScript. They are related to real arrays by the fact that they have the length property and properties with names in the form of numbers that correspond to the elements of the array. Examples include the DOM collection of the NodeList and the pseudo- NodeList arguments , available within any function / method.

1. Using brute force methods for real arrays


At least most, if not all, methods of enumerating real arrays can be applied to enumerate massive-like objects.

The for and for...in constructions can be applied to array-like objects in exactly the same way as with real arrays.

forEach and other Array.prototype methods also apply to array-like objects. To do this, use the call Function.call or Function.apply .

For example, if you want to apply forEach to the childNodes property of the Node object, this is done like this:

 Array.prototype.forEach.call(node.childNodes, function(child) { //  -   child }); 

For the convenience of reusing this technique, you can declare a link to the Array.prototype.forEach method in a separate variable and use it as an abbreviation:

 // (,         ) var forEach = Array.prototype.forEach; // ... forEach.call(node.childNodes, function(child) { //  -   child }); 

If there is an iterator in a mass-like object, then it can be used explicitly or implicitly to iterate over the object in the same way as for real arrays.

2. Conversion to real array


There is also another very simple way to iterate over an array-like object: convert it into a real array and use any of the above methods for iterating over real arrays. For the transformation, you can use the universal method Array.prototype.slice , which can be applied to any array-like object. This is done very simply, as shown in the example below:

 var trueArray = Array.prototype.slice.call(arrayLikeObject, 0); 

For example, if you want to convert a NodeList collection into a real array, you need something like this code:

 var divs = Array.prototype.slice.call(document.querySelectorAll("div"), 0); 

Update : As noted in the rock and torbasow comments , in ES6, instead of Array.prototype.slice you can use the more visual method Array.from .

3. A note on runtime objects


If you apply Array.prototype methods to Array.prototype objects (such as the DOM collection), then you should keep in mind that the correct operation of these methods is not guaranteed in all execution environments (including browsers). It depends on the behavior of a particular object in a particular execution environment, more precisely, on how the abstract operation HasProperty implemented in this object. The problem is that the ES5 standard itself allows for the possibility of an incorrect behavior of an object in relation to this operation (see §8.6.2 ).

Therefore, it is important to test the operation of the Array.prototype methods in each execution environment (browser) in which you plan to use your application.

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


All Articles