[Issue 786] Learn more about the for loop in JavaScript

image
Preface

For such a detailed sharing of a cycle, I believe you will gain something after reading it. This article is shared by the author of the front-end morning reading class column @ compiled youth authorization.


The text starts here~


In ECMAScript5 (ES5 for short), there are three for loops, namely:

  • Simple for loop

  • for-in

  • forEach


In ECMAScript6 (ES6 for short) released in June 2015, a new loop was added, which is:

  • for-of


Let's take a look at these four for loops.


Simple for loop


Let's take a look at the most common way of writing:

image


When the length of the array does not change during the loop, we should store the length of the array in a variable, which will get better efficiency. The following is an improved way of writing:

image


for-in


Under normal circumstances, we can use for-in to traverse the contents of the array, the code is as follows:

image


In general, the results of the operation are as follows:

image


But doing so often causes problems.


The truth about for-in


The for-in loop traverses the properties of the object, not the index of the array. Therefore, the objects traversed by for-in are not limited to arrays, but objects can also be traversed. Examples are as follows:

image


The results are as follows:

image


It should be noted that the order of for-in traversal of attributes is not certain, that is, the order of output results has nothing to do with the order of attributes in the object, nor with the alphabetical order of attributes, nor with any other order.


The truth about Array


Array is an object in Javascript, and the index of Array is the property name. In fact, the "array" in Javascript is a bit misleading. Array in Javascript is not like arrays in most other languages. First, the Array in Javascript is not continuous in memory, and second, the index of the Array does not refer to the offset. In fact, the index of Array is not Number type, but String type. The reason why we can use the wording like arr[0] correctly is that the language can automatically convert 0 of the Number type to "0" of the String type. Therefore, there is never an Array index in Javascript, but only properties like "0", "1", etc. Interestingly, every Array object has a length property, which makes it behave more like arrays in other languages. But why doesn't the length property output when traversing the Array object? That's because for-in can only traverse "enumerable properties", length is a non-enumerable property, in fact, Array objects have many other non-enumerable properties.


Now, let's go back and take a look at the example of using for-in to loop the array. Let's modify the previous example of traversing the array:

image


The result of the operation is:

image.png


We see that the for-in loop accesses our new "name" attribute, because for-in traverses all the attributes of the object, not just the "index". At the same time, it should be noted that the index values ​​output here, namely "0", "1", and "2" are not of the Number type, but of the String type, because they are output as attributes, not indexes. Does that mean that we can only output the contents of the array without adding new properties to our Array object? the answer is negative. Because for-in not only traverses the attributes of array itself, it also traverses all enumerable attributes on the array prototype chain. Let's look at an example:image


The result of the operation is:

image

At this point, we can find that for-in is not suitable for traversing the elements in the Array, it is more suitable for traversing the properties of the object, which is also the original intention of its creation. There is one exception, that is, sparse arrays. Consider the following example:

image

For-in only traverses existing entities. In the above example, for-in traverses 3 times (traversing elements with attributes "0", "100", and "10000" respectively, and ordinary for loop will traverse 10001 times) . Therefore, if handled properly, for-in can also play a huge role in traversing the elements in the Array.


To avoid duplication of effort, we can wrap the above code:

image.png


Examples of usage are as follows:

image.png


for-in performance


As mentioned above, each iteration operation will search for instance or prototype properties at the same time. Each iteration of the for-in loop will incur more overhead, so it is slower than other loop types, and the speed is generally 1/7 of other loop types. Therefore, unless you explicitly need to iterate over an object with an unknown number of attributes, you should avoid using for-in loops. If you need to traverse a limited number of known attribute lists, it is faster to use other loops, such as the following example:


In the above code, the attributes of the object are stored in an array. Compared with the for-in search for each attribute, the code only focuses on the given attribute, which saves the overhead and time of the loop.


forEach

image


In ES5, a new loop is introduced, the forEach loop.

image

operation result:

image

The forEach method executes the callback function once for each item in the array that contains a valid value. The items that have been deleted (using the delete method, etc.) or have never been assigned will be skipped (excluding those items with undefined or null values). The callback function will be passed three parameters in turn:

  • The value of the current item in the array;

  • The index of the current item in the array;

  • The array object itself;


It should be noted that the range of forEach traversal will be determined before the first call to callback. Items added to the array after calling forEach will not be accessed by callback. If the existing value is changed, the value passed to callback is the value at the moment forEach traverses them. Deleted items will not be traversed.

image.png

operation result:


image

The index here is of Number type, and it does not traverse the properties on the prototype chain like for-in.


Therefore, when using forEach, we don't need to specifically declare the index and traversed elements, because these are all used as the parameters of the callback function.


In addition, forEach will traverse all the elements in the array, but ES5 defines some other useful methods, the following is a part:

  • every: The loop returns after the first return false

  • some: The loop returns after the first return true

  • filter: returns a new array, the elements in the array satisfy the callback function

  • map: process the elements in the original array before returning

  • reduce: Process the elements in the array in turn, use the result of the previous processing as the input for the next processing, and finally get the final result.


forEach performance


First of all, thank @papa pa for the reminder, only to find that my previous understanding is wrong.


You can look at jsPerf. The results of testing under different browsers are that forEach is not as fast as for. If you put the test code in the console, you may get different results. The main reason is that the execution environment of the console is different from the real code execution environment.


for-of


Let's look at an example first:

image


The result of the operation is:

image


Why introduce for-of?


To answer this question, let's first take a look at the defects of the three for loops before ES6:

  • forEach cannot break and return;

  • The disadvantage of for-in is more obvious. It not only traverses the elements in the array, but also traverses the custom properties, and even the properties on the prototype chain are accessed. Moreover, the order of traversing the array elements may be random.


Therefore, in view of the above shortcomings, we need to improve the original for loop. But ES6 will not break the JS code you have written. Currently, thousands of Web sites rely on for-in loops, and some of them even use it for array traversal. If you want to add support for array traversal by modifying the for-in loop, this will become even more confusing. Therefore, the Standards Committee has added a new loop syntax in ES6 to solve the current problem, that is, for-of.


So what can for-of do?

  • Compared with forEach, it can respond correctly to break, continue, and return.

  • The for-of loop not only supports arrays, but also supports most array-like objects, such as DOM nodelist objects.

  • The for-of loop also supports string traversal, which treats the string as a series of Unicode characters to traverse.

  • for-of also supports Map and Set (both are new types in ES6) object traversal.


To sum up, the for-of loop has the following characteristics:

  • This is the most concise and straightforward syntax for traversing array elements.

  • This method avoids all the flaws of for-in loops.

  • Unlike forEach, it can correctly respond to break, continue, and return statements.

  • It can traverse not only arrays, but also array-like objects and other iterable objects.


But it should be noted that the for-of loop does not support ordinary objects, but if you want to iterate the properties of an object, you can use the for-in loop (this is also its job).


The last thing to say is that another method introduced by ES6 can also traverse the values ​​of an array, and that is Iterator. Last example:

image


Guess you like

Origin blog.51cto.com/15080028/2595036