Click here to Skip to main content
Click here to Skip to main content

JavaScript Performance Tips - Part 2

, 20 Sep 2013 CPOL
Rate this:
Please Sign up or sign in to vote.
JavaScript performance tips - Part 2

Introduction

Continuing from where I left last time, let's delve a bit deeper into performance aspects of JavaScript. While Part 1 was about basics, this section explores certain memory management techniques in JavaScript. So before you proceed, please refresh your memory on prototype and its internals.  

Background

This tip assumes some basic knowledge of prototype and some internals on how functions work in JavaScript. Readers can read this tip independent of Part 1

Tips on Performance

  1. The problem with functions inside functions:
    function Person(fname,lname) {
        this.firstName = fname;
        this.lastName = lname;
     
        this.getName = function(){
            return this.firstName + ' ' + this.lastName;
        }
     
    }
    //lets say you are doing something like this in your code
    var p1 = new Person("Jack", "Smith");
    var p2 = new Person("John", "Doe");

    Everytime you create a new person, JS Engine allocates memory for firstName, lastName and getName. I don't mean to say that this is wrong but this is inefficient. Isn't it? So, what's the solution? Move getName to prototype!

  2. Move common functions to prototype:
    //Better
    Person.prototype = {
       getName : function(){
           return this.firstName + ' ' + this.lastName;
       }
    }

    Once we move the getName method to prototype, you will observe that p1 and p2 will just hold a reference to the single memory block allocated for getName. How will this help? Well, if your app is creating many Person objects on the fly, less memory is allocated by browser when creating new Persons and hence the Garbage collector which kicks in intermittently in the app life cycle will quickly do its job and move on improving your app's user experience by reducing the flicker.

  3. Array memory management:
    function foo() {
        var arr = [];
        ....
        arr.push(1);
        ....
        //May be now you want to clean up the array!
        arr = [];
        arr.push(2);
        ....
    }

    What's wrong with the above code? The function foo simply creates an array, pushes an item and then somewhere down the line cleans up the array and pushes another item. Well, first looks can be deceiving at times! Observe closely that second time, the array is recreated. So effectively, JS Engine requests for another memory block and the browser allocates one. The older memory block is awaiting garbage collection. Hmm... is it necessary to recreate an array? Well, the intention was to just clean up not allocate a new array. So, what's the solution?

        //lets try the cleanup differently!
        arr.length = 0;

    Observe that if you replace the above statement with the cleanup statement in foo, you still get the same result! The difference is that no new memory block is allocated by the browser in this case.

  4. Keep private methods outside the plugin's return.
    (function($){
       $.fn.pluginName = function(config){
          return this.each(function(){
             //...
             function doSomething(){};
          });
       }
    })(jQuery);
     
    $(".myClass").pluginName({o:1});

    The problem with the above jQuery plugin is that the function doSomeThing is created for each iteration of the selector. So if your jQuery selector returns 10 DOM elements which have a CSS class called 'myClass', your plugin is consuming lot of memory by requesting the engine to allocate 10 blocks for doSomething. How can we avoid this? Well, simply move your private function outside of this.each iteration!

    //This is cleaner and efficient
    (function($){
       $.fn.pluginName = function(config){
          return this.each(function(){
             //....
             myPrivates.doSomething();
          });
          var myPrivates = {
            doSomething : function(){};
          };
       }
    })(jQuery);
     
    $(".myClass").pluginName({o:1});

    You don't necessarily have to create a private object, just moving out doSomething out of the iterator is good enough!

  5. Avoid anonymous functions inside setTimeout or setInterval:
      setTimeout(function(){ 
        //do Something
      }, 2000);

    What's wrong with the above code? You should have guessed it by now if you got the theme of this article. Smile :-| Yes, the JS Engine simply creates a new anonymous function every 2 seconds! More garbage and you know the consequence! The solution is obviously to use a named function and reference it inside setTimeout.

      //Much better
      function myCallback(){ 
        //do Something
      };
      setTimeout(myCallback, 2000);
  6. See if you can get away by using Static classes in your app. Use instance classes only when necessary. The idea is to use memory sparingly - only when it's an absolute necessity.
      //Simpler and better
       var MyApp = MyApp || {};
       MyApp = (function () {
        var doSomething = function() { }
        return {
            init: function (a) {
                
            };
        };
    })();
    MyApp.init();

Parting Note

The improvements listed above are common pitfalls which can be avoided in our day to day coding. I hope you find these tips useful. If yes, please share it with the developer community.

Happy learning. Smile :-|

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Rajesh Udupi
Web Developer
India India
I'm a Software Developer with extensive programming experience on front end apps.

Comments and Discussions

 
QuestionMy vote of 5 PinmemberNerudo Mregi24-Sep-13 0:02 
GeneralMy vote of 5 PinprofessionalBrian A Stephens19-Sep-13 6:30 
GeneralRe: My vote of 5 PinmemberRajesh Udupi19-Sep-13 23:37 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.141015.1 | Last Updated 20 Sep 2013
Article Copyright 2013 by Rajesh Udupi
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid