Tuesday, August 18, 2015

Multiple ways to iterate an array in Javascript

Javascript now seems the way to survive in software industry at least for the next 5 years. I have written a post earlier describing why developers should invest time in learning good parts of Javascript. This is small post where I would like to show how many ways are there in Javascript to loop through an array.

The purpose of this post is not to compare and find out which is the best way. For that please refer this link. Lets start.

Simple javascript JSON array

The iteration needs an array at the minimum. Below is an array which we are going to use.

var strings = ["Joy", "George"];

When we iterate we need to have a test mechanism to show the output. I am just defining an output function which handles it. For the time being we are showing in alert box.

function output(msg) {  
     alert(msg);  
 }
Now lets start exploring different ways to iterate this array.

  1. Using for(;;)

  2. This is the simplest way to iterate any collection. It uses a index pointer variable and gets element from the array using that pointer.Below is the code which does it.

    $scope.loopStringsUsingFor = function () {
            for (i = 0; i < strings.length; i++) {
                output("i=" + i + ", strings[i]=" + strings[i]);
            }
    };

    We can see that there is a $scope variable and the function is assigned to it. This is because I am using AngularJS in jsFiddle.net and this is the way I can associate click handler. The jsFiddle.Net linke is given at the end of this post. It will help to see this code running and play around with the same.
    The output will be 2 alert boxes with the below content respectively.

    i=0 , strings[i]=Joy
    i=1 , strings[i]=George
  3. Using for(var in array)

  4. This is similar to the iteration model available in other languages such as C#. It does not need the index variable. But in Javascript, its not working exactly the same way it works in other languages. Lets see the code below

    $scope.loopStringsUsingForIn = function () {
            for (s in strings) {
                output("s=" + s + ", strings[s]=" + strings[s]);
            }
    };

    The difference with the other languages is clear. In other languages s will be the element in the array. But here s is again the index and we need to use that index to get the string object. The output will be

    s=0, strings[s]=Joy
    s=1, strings[s]=George

    If people are coming from other languages, they will expect string object to be available in the s variable but it will never be. 

  5. Using for(var of array)

  6. This is more similar to the iterations of other languages such as C#. But unfortunately this is available  only from ES6 specs which is released in 2015. If we are targeting application towards global audience, this may not work. See the browser compatibility for more details.

    $scope.loopStringsUsingForOf = function () {
            for (s of strings) {
                output("s="+s);
            }
    }

    The output will be 
    s=Joy
    s=George
  7. Using Array.forEach(function(element,index))

  8. Here we are iterating the array and for each element in the array the function which is passed as argument will be invoked. The element will be the actual string value and index will be the pointer. Lets see how this works

    $scope.loopStringsUsingArrayForEach = function () {
            strings.forEach(function (element, index) {
                output("index=" + index + ",element=" + element);
            });
    }

    The output will be as follows

    index=0,element=Joy
    index=1,element=George
  9. Using Object.keys(array).forEach(function(element,index))

  10. This iterate through the keys in array. Keys is again an array. Which means we need to find the actual object using indexing mechanism. See the code below

    $scope.loopStringsUsingObjectKeysForEach = function () {
            Object.keys(strings).forEach(function (element, index) {
                output("index=" + index + ",element=" + element + ",strings[element]=" + strings[element] + ",strings[index]=" + strings[element]);
            });
    }

    Since its looping through the keys of array it will return index as well as element as 0,1,..Then the indexing mechanism brings the actual data. The output will be as follows

    index=0,element=0,strings[element]=Joy,strings[index]=Joy
    index=1,element=1,strings[element]=George,strings[index]=George

  11. Using Array.map(function(element))

  12. This is another method to execute a function against all the elements in a array. Lets see the code 

    $scope.loopStringsUsingMap= function(){
            strings.map(function(s){
                output("s="+s);
            });
    }.

    The output will be

    s=Joy
    s=George

  13. Using Array.filter

  14. This technique again uses another method named filter defined on Array. Below is the code

    $scope.loopStringsUsingArrayFilter = function () {
            strings.filter(function (element) {
                output("s=" + element);
            });
    }

    Output is same as
    s=Joy
    s=George

  15. Using Array.every(function(element,index))
  16. This is not intended for iterating. But for testing all the elements in the array for condition. If any element fails on test, it won't iterate to next element. The return boolean value indicate whether the test is success or not. If we return false or don't return any value the iteration will not continue to next element. Instead it just stops. Code below

    $scope.loopStringsUsingArrayEvery = function () {
            strings.every(function (element, index) {
                output("element=" + element + ", index ="+index);
                return true;
            });
    }

    Output will be
    element=Joy,index=0
    element=George,index=1

  17. Using Array.pop()

  18. This is not exactly iterating the array. But its taking each item from the array. Once this loop is completed the array will be empty.

    $scope.loopStringsUsingArrayPop = function () {
            while (s = strings.pop()) {
                output("s=" + s);
            }
            output("length of strings="+strings.length);
    }

    Output will be
    
    
    s=George
    s=Joy
    length of strings=0
    
    
    There are more methods on Array which we can use for iterating. Please refer the documentation for more details.
  19. Using Symbol.Iterator

  20. This specification came in ES6 in 2015. So only very latest browsers support this. Code goes as below.
    $scope.loopStringUsingIterator = function () {
            var iter = strings[Symbol.iterator]();
            while (s = iter.next().value) {
                output("s="+s);
            }
    }

    Output will be
    s=Joy
    s=George
  21. Using angular.forEach(array,function(element))

  22. Now most of us would be in a state of confusion which one should use. How to make sure which is supported where etc...This is the exact time frameworks comes to help us. Most of the frameworks provide a mechanism to iterate arrays. The below code snippet is applicable only if we are using AngularJS script is included in the html page.

    $scope.loopStringsUsingAngularForEach = function(){
            angular.forEach(strings,function(s){
                output("s="+s);
            });
    };

    Output will be 

    s=Joy
    s=George

    This works in most of the places. Similarly jQuery has mechanism to iterate arrays.
If we use these frameworks we can relax from these repeating general concerns of will this work in other browsers and focus on our business problems and features. Why should we bother to a problem which everybody faces and solved already?

There are more complicated scenarios when we deal with complex objects. Explaining every scenario will be very difficult within a post. Will try to address complex objects related things in another post.

Please go to the jsfiddle to see the complete code

No comments: