This article is a combined effort of Innofied Javascript developers Puja Deora and Subhajit Ghosh)

We have been working on a project for past 8 months (ongoing). Over the course of this project, we have learnt that small tweaks to general coding practices goes a long way in improving the overall performance of the code.

In this article, we will discuss some of these common JavaScript practices and tricks to code optimization that improve the overall efficiency and performance of our code. Most of the techniques described below are fairly intuitive once we grasp the underlying problem or overhead.

1. Chain of Command

JQuery Chaining is a very powerful feature of jQuery that connects multiple functions and events on a particular selector. The following example shows how chaining makes our code shorter and faster.
Code 1

 
 
 
 
 
 

JavaScript

 
1
2
3
$('.element').removeClass('old');
$('.element').addClass('new');
$('.element').show();

Code 2

 
 
 
 
 
 

JavaScript

 
1
2
$('.element').removeClass('old')
.addClass('new').show();

The problem with code 1 is that for every statement, jQuery has to search the entire DOM and find the element and after that execute the attached function on it. But when chaining is used, jQuery has to find the element only once and it will execute all the attached functions one by one. So, Code 2 is optimized.

2. Event Management

Using jQuery, we can attach events to an element in the following two ways:

Code 1

 
 
 
 
 
 

JavaScript

 
1
$(‘selector’).click(function() {});

Code 2

 
 
 
 
 
 

JavaScript

 
1
$('parent-selector').on('click', 'selector', function callback(){});

The second method is better as it allows us to bind events to dynamic HTML elements.

3. Out of Scope

Every time we define a new function and create a new closure, javascript adds a level to its scope chain. When the browser resolves properties, each level of the scope chain must be checked. In other words, JavaScript looks at the first item in the scope chain, and if it doesn’t find the variable, it bubbles up the chain until it hits the global object.

That’s why global scopes are slow. They are worst-case scenarios for object lookups.

Example Code

 
 
 
 
 
 

JavaScript

 
1
2
3
4
5
6
7
8
9
10
var outer = 'outer';
var sampleFunction = function() {
    var inner = 'inner';
    return function() {
        var efficient = 'efficient';
        outer;
        inner;
        efficient;
    };
};

Here when the function is invoked referencing outer is slower than referencing inner, which is slower than referencing efficient.

4. Power of Native functions and constructs

Its good to be aware of native constructs provided by ECMAScript as it saves us from having to write our own algorithms. Some commonly used constructs are-

  • Math.floor() and Math.round() for arithmetic operations
  • (new Date()).getTime() for timestamps
  • String.prototype.match() and String.prototype.replace() for regexes
  • parseInt(n, radix) for changing numeral systems
  • === instead of == for faster type-based comparison
  • instanceof for checking type up the hierarchy
  • & and | for bitwise comparisons.
  • && and || operators instead of simple if-else statements.

5. Use ‘this’ the right way

In case of using asynchronous code blocks, a common practice is to use global or closure variables to refer to object properties outside the scope of the asynchronous block. For example:

 
 
 
 
 
 

JavaScript

 
1
2
3
4
5
6
7
var Test = function() {
    var me = this;
    this.x = 5;
    return function() {
console.log(me.x);
    };
};

As discussed in point number 3 above, this takes longer time as the closure variables (in this example, me) are held at a higher level of the scope chain. We can improve this by binding the correct scope to our asynchronous function when we call them. For example,

 
 
 
 
 
 

JavaScript

 
1
2
3
4
5
6
7
var Test = function(callback) {
    this.x=5
    callback.call(this);
};
Test(function(){
    console.log(this.x)
}); //output is 5

6. Define class methods with prototype

We can define a method of a class in the following two ways:

Method 1

 
 
 
 
 
 

JavaScript

 
1
2
3
4
MyClass = function() {
    var privateVariable;
    this.privilegedMethod = function() {};
};

Method 2

 
 
 
 
 
 

JavaScript

 
1
MyClass.prototype.publicMethod = function() {};

When we define a class method using prototype (Method 2), only one copy of the function is created which is shared by all object instances of the class. The context within the function will refer to the instance which calls it. Hence, it is a more efficient way of defining methods than using ‘this’.

7. Avoid referencing Object properties

Reading an object property takes longer than reading a variable. It would do us good to remember this when we are referring to some object property frequently. We could improve our code’s performance by storing this property in a temporary variable.

Method 1

 
 
 
 
 
 

JavaScript

 
1
2
3
4
5
6
7
var stringFill1 = function(string, count) {
    var result = '';
    while (result.length < count) {
        result += string;
    }
    return result;
}; // Execution time for this function is 47.297 microseconds

Method 2(Optimized)

 
 
1
2
3
4
5
6
7
var stringFill1 = function(string, count) {
    var result = '';
    while (count-- > 0) {
        result += string;
    }
    return result;
};// Execution time for this function is 27.68 microseconds

8. Batch style updates

In case we need to make several style updates for a particular DOM element, it is better to apply those changes at once instead of applying them one by one. This prevents the UI from being rendered repeatedly. In the following example, Method 2 is better than Method 1.

Method 1

 
 
 
 
 
 

JavaScript

 
1
2
3
4
5
6
7
// This will incur 5 screen refreshes
jQuery('.element')
    .width(600)
    .height(400)
    .css('position': 'absolute')
    .css('top', '200px')
    .css('left', '200px');

Method 2

 
 
 
 
 
 

JavaScript

 
1
2
3
4
5
6
7
8
// Let jQuery handle the batching
jQuery('.element').css({
     width: '600px',
     height: '400px',
     position: 'absolute',
     top: '200px',
     left: '200px'
);

When working with similar cases as described in the above example, there is another way that’s far more efficient than using jQuery’s CSS method. We could add a new class to the DOM element and write the style changes against that class in our CSS file.

Efficient Method

 
 
 
 
 
 

JavaScript

 
1
jQuery('.element').addClass('prefferedClass');

9. Build DOM ‘off-line’

Every time we add a DOM element to the UI, it refreshes the entire screen. We can improve that by building DOM ‘off-line’ and adding it to the UI at once.

Method 1

 
 
 
 
 
 

JavaScript

 
1
2
3
4
var list = $('<ul></ul>');
$(list).append('<li>Sample1</li>');
$(list).append('<li>Sample2</li>');
$(list).append('<li>Sample3</li>');

Method 2(Optimized)

 
 
1
2
3
4
5
6
var list = $('<ul></ul>'),
    htmlBuffer=[" <li>Sample1</li>",
"<li>Sample2</li>",
"<li>Sample3</li>"].join("");
 
$(list).append(htmlBuffer);

10. Many-to-one

After we have completed developing our .js files, we can pass them through a javascript minimizer tool (such as JsMin) which removes the unnecessary code blocks (read comments and white spaces). This way, we just have to add one minified script file to our HTML. Its better because a request to fetch one comparatively larger file executes faster than the request to fetch multiple smaller files.

11. Dependency Manager

The idea is to load modules to the browser as and when they are required. When a user requests for a page, the first thing they notice is the HTML content. The functionality is required only after they get familiarised with the layout. We can achieve this by working with dependency managers likeRequireJS or Browserify.

12. Better String concatenation

String concatenation causes major problems with Internet Explorer 6 and 7 garbage collection performance.

Method 1

 
 
 
 
 
 

JavaScript

 
1
var longString = "This is a long String" + "So the question is how to concatenate a string" + "in a better way";

Method 2

 
 
 
 
 
 

JavaScript

 
1
var longString = ["This is a long String" , "So the question is how to concatenate a string" , "in a better way"].join(" ");

When we concatenate some substrings to create a larger string, all intermediate results are stored in temporary variables. Therefore the second method is optimized as it requires lesser memory for execution.

13. Indexing power of Javascript Objects

Lengthy if-else blocks can be reduced to a single line of code. All we need to do is create a Javascript object to map each condition to a function name. It works in a manner similar to HashMap data structures. The following example illustrates this technique.

Method 1

 
 
1
2
3
4
5
6
7
if(action === 'add'){
  onAdd();
}else if(action === 'edit'){
  onEdit();
} else if(action === 'delete') {
  delete();
}

Method 2(Optimized)

 
 
1
2
3
4
5
6
var actions = {
  'edit' : 'doEdit',
  'delete': 'delete',
  'add': 'onAdd'
};
actions[action]();

14. Primitive vs Reference variable types

Primitive variables and reference variables behave differently when we pass them as parameters for a function call. A copy of primitive variables is created in the function whereas only a light-weight reference is passed to the new function, in case of reference type variables. So whenever we need to pass a few parameters to a function, it is better to create a config object and pass a reference to that instead.

15. Use defineProperty/defineProperties

defineProperty gives us more control over the behaviour of object properties that we define. We get options to- prevent further modification or deletion after an object property has been defined, control whether the property shows up during enumeration or not and so forth.

Let’s consider the example of data structure Stack. We define the push method for Stack as follows:

 
 
 
 
 
 

JavaScript

 
1
2
function Stack(){};
Stack.prototype.push = function(x){/* */}

Since we are dealing with Stack, ‘push’ will be an integral method for any implementation. We would be referring it repeatedly and wouldn’t want anything to modify, overwrite or delete our definition. This can be controlled by defining it as follows:

 
 
 
 
 
 

JavaScript

 
1
2
3
4
5
6
7
8
9
function Stack() {
};
Object.defineProperties(Stack.prototype, {
    push: {
        writable: false,
        configurable: true,
        value: function (x) { /* ... */ }
    }
});

Another advantage of working with defineProperty is that we can use the getter/setter methods to get or set the value for an object property.

 
 
 
 
 
 

JavaScript

 
1
2
3
4
5
6
7
8
9
10
11
12
var square ={
    width: 20,
    height: 30
};
 
Object.defineProperty(square, 'area', {
    get: function(){
        return this.width*this.height;
    }
});
 
console.log(square.area);

Here the get method is called implicitly when we refer to square.area. Read here for more information on defineProperty.

These are some of the many best practices that we have found effective. We hope you find these helpful. Do comment and share optimization techniques from your experience. Happy coding.

Code optimization and organization in Javascript / jQuery的更多相关文章

  1. 在线运行Javascript,Jquery,HTML,CSS代码

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" http://www.w3.org/TR/xht ...

  2. javascript --- jQuery --- Deferred对象

    javascript --- jQuery --- Deferred对象 javascript的函数式编程是多么引人入胜,jQuery使代码尽可能的精简,intelligent! defer - 必应 ...

  3. 使用Javascript/jQuery将javascript对象转换为json格式数据 - 海涛的CSDN博客 - 博客频道 - CSDN.NET

    body{ font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI& ...

  4. Handlebars的基本用法 Handlebars.js使用介绍 http://handlebarsjs.com/ Handlebars.js 模板引擎 javascript/jquery模板引擎——Handlebars初体验 handlebars.js 入门(1) 作为一名前端的你,必须掌握的模板引擎:Handlebars 前端数据模板handlebars与jquery整

    Handlebars的基本用法 使用Handlebars,你可以轻松创建语义化模板,Mustache模板和Handlebars是兼容的,所以你可以将Mustache导入Handlebars以使用 Ha ...

  5. JavaScript jQuery 中定义数组与操作及jquery数组操作

    首先给大家介绍javascript jquery中定义数组与操作的相关知识,具体内容如下所示: 1.认识数组 数组就是某类数据的集合,数据类型可以是整型.字符串.甚至是对象Javascript不支持多 ...

  6. VS Code - Debugger for Chrome调试JavaScript的两种方式

    VS Code - Debugger for Chrome调试JavaScript的两种方式 最近由于出差的缘故,博客写的不是很多,一直想写一篇VS Code - Debugger for Chrom ...

  7. javascript/jquery读取和修改HTTP headers

    javascript/jquery读取和修改HTTP headers jquery修改HTTP headers jQuery Ajax可以通过headers或beforeSend修改request的H ...

  8. 大量Javascript/JQuery学习教程电子书合集

    [推荐分享]大量Javascript/JQuery学习教程电子书合集,送给有需要的人   不收藏是你的错^_^. 经证实,均可免费下载. 资源名称 资源大小   15天学会jQuery(完整版).pd ...

  9. [推荐分享]大量Javascript/JQuery学习教程电子书合集,送给有需要的人

    不收藏是你的错^_^. 经证实,均可免费下载. 资源名称 资源大小   15天学会jQuery(完整版).pdf 274.79 KB   21天学通JavaScript(第2版)-顾宁燕扫描版.pdf ...

随机推荐

  1. C#打印图片

    打印的原理是:生成mdi文件,系统碰到mdi的时候会自动以打印的方式处理.所以,不管用什么模板,什么方式:能在PrintPage事件处理中,生成一张要打印内容的图片就OK了! C#实现打印源码如下: ...

  2. 使用p3p跨域设置Cookie

    有些时候不能将url上的参数传来传去,比如与调用某开放平台上的接口,这时候可能需要借助Cookie来进行处理了,但这里可能又涉及到跨域的问题. 如果浏览器开启了对Cookie的支持,按照Cookie ...

  3. Snmp学习总结(六)——linux下安装和配置SNMP

    一.安装SNMP 1.1.下载Net-SNMP的源代码 选择一个SNMP版本,比如5.7.1,下载地址如下:http://sourceforge.net/projects/net-snmp/files ...

  4. Flex+blazeds实现与mySQL数据库的连接(已成功实现此文的例子)

    http://bdk82924.iteye.com/blog/1067285 几个下载地址 blazeds_turnkey_3-0-0-544.zip 下载地址:http://download.mac ...

  5. DirectX - dds图片格式(DDSURFACEDESC2)

    DDS是DirectDraw Surface的缩写,它是DirectX纹理压缩(DirectX Texture Compression,简称DXTC)的产物. DXTC减少了纹理内存消耗的50%甚至更 ...

  6. 无法上外网, ping网关ping不通的解决——arp命令

    转自:http://jingyan.baidu.com/article/3c48dd34873909e10be35894.html 转自:http://man.linuxde.net/arp 用来管理 ...

  7. JForum 源码分析

    怎么才算好的源码分析呢?当然我这个肯定不算.我想大概分为几个层面吧,写写注释那算最基本的了,写写要点思路和难点,算是还不错拉,再难的就是跳出源码举一反三,形成自己的一套思路吧.好好努力吧. 这次针对的 ...

  8. Java web实时进度条整个系统共用(如java上传、下载进度条、导入、导出excel进度条等)

    先上图: 文件上传的: 2017-05-04再次改进.在上传过程中用户可以按 Esc 来取消上传(取消当前上传,或者是全部上传)... 2019-03-26更新进度条显示体验 从服务器上压缩下载: 从 ...

  9. 无耻之徒(美版)第七季/全集Shameless US迅雷下载

    英文全名Shameless (US),第7季(2016).本季看点:<无耻之徒>(Shameless)第七季.本季故事起始于「一个月之后」,Frank从昏迷中醒来后得知亲人背叛了他,于是向 ...

  10. 尼基塔第一季/全集Nikita迅雷下载

    本季Nikita Season 1 第一季(2010)看点:尼基塔曾经是一个性格叛逆的问题少女,因为犯下重罪被处以死刑.一家秘密间谍机构将尼基塔从死牢里救了出来,伪造了她的死亡,将她训练成了一名间谍和 ...