Javascript code optimization and javascript code

Source: Internet
Author: User

Javascript code optimization and javascript code

This article will introduce several key points of the JS programming style in detail.

Loose coupling

Loose coupling is achieved when you modify a component without changing other components.

1. Remove JS from CSS: Do not use CSS expressions

// Bad practice. box {width: expression (document. body. offsetWidth + 'px ')}

2. Remove CSS from JS: when modifying the CSS style through JS, use className or classList. Do not change the style one by one.

// Bad practice 1 ele. style. color = 'red'; ele. style. left = '10px '; // difficult method: ele.style.css Text = 'color: red; left: 10px ;';
. Reveal {color: red; left: 10px;} // good practice 1 ele. className + = 'reveal'; // good practice 2 ele. classList. add ('reveal ');

3. Extract JS from HTML: Put the JS file into an external file

4. Extract HTML from JS: Do not splice the DOM structure in innerHTML, but use a string template, such as handlerbars.

Global Variables

Creating global variables is considered a bad practice, especially in the context of team development. As the amount of Code increases, global variables will lead to some very important maintainability difficulties. The more global variables, the higher the probability of introducing errors.

Generally, there are three solutions:

1. Zero global variables

The implementation method is to use an immediate call function IIFE and place all scripts in it

(function(){ var doc = win.document;})(window);

This mode is applicable to a limited number of scenarios. This method is unavailable if the code needs to be depended on by other codes or needs to be constantly expanded or modified during running.

2. Single global variables and namespaces

Depends on as few global variables as possible, that is, to create only one global variable, using the single-variable mode, such as YUI or jQuery

A single global variable, that is, the unique global object name created is unique and all functional code is mounted to this global object. Therefore, each possible global variable becomes the attribute of the unique global variable, so that multiple global variables are not created.

A namespace is a simple functional group represented by a single attribute of a global object. For example, all methods in Y. DOM are related to DOM operations, and all methods in Y. Event are related to events. A common convention is that each file uses a new global object to declare its own namespace.

3. Modules

A module is a common feature segment that does not create a new global variable or namespace. Instead, all the code is stored in a single function that indicates executing a task or publishing an interface. You can use a name to represent this module. Similarly, this module can depend on other modules.

Event Processing

Code related to event processing is coupled with the event environment, resulting in poor maintainability.

1. Isolate application logic

It is a best practice to extract the application logic from all event handlers and split the application logic and event processing code.

// Bad practice function handleClick (event) {var popup = document. getElementById ('popup'); popup. style. left = event. clientX + 'px '; popup. style. top = event. clientY + 'px '; popup. className = 'reveal';} addListener (element, 'click', handleClick); // good practice var MyApplication = {handleClick: function (event) {this. showPopup (event) ;}, showPopup: function (event) {var popup = document. getElementById ('popup'); popup. style. left = event. clientX + 'px '; popup. style. top = event. clientY + 'px '; popup. className = 'reveal' ;}}; addListener (element, 'click', function (event) {MyApplication. handleClick (event );});

2. Do not distribute event objects

The application logic should not rely on the event object to correctly complete the function. The method interface should indicate which data is necessary. If the code is unclear, a bug may occur. The best way is to let the event handler use the event object to process the event, and then get all the required data and pass it to the application logic.

// Improved method var MyApplication = {handleClick: function (event) {this. showPopup (event. clientX, event. clientY) ;}, showPopup: function (x, y) {var popup = document. getElementById ('popup'); popup. style. left = x + 'px '; popup. style. top = y + 'px '; popup. className = 'reveal' ;}}; addListener (element, 'click', function (event) {MyApplication. handleClick (event );});

When processing an event, it is best to make the event program a unique function that comes into contact with the event object. The event handler should perform any necessary operations on the event object before entering the application logic, including blocking event bubbling, and should be directly included in the event handler.

// Improved method var MyApplication = {handleClick: function (event) {event. preventDefault (); event. stopPropagation (); this. showPopup (event. clientX, event. clientY) ;}, showPopup: function (x, y) {var popup = document. getElementById ('popup'); popup. style. left = x + 'px '; popup. style. top = y + 'px '; popup. className = 'reveal' ;}}; addListener (element, 'click', function (event) {MyApplication. handleClick (event );});
Configuration data

Code is nothing more than defining a set of commands for computers to execute. We often pass data into the computer, and the command operates the data and finally produces a result. When data has to be modified, unnecessary risks may occur. Key data should be extracted from the code

Configuration data is a value that is intended to be written to an application and may be modified in the future, including the following content:

1. URL2: string to be presented to the user. 3. duplicate value. 4. configuration item. 5. Any value that may change

The following describes the practices of unprocessed configuration data.

// Bad practice function validate (value) {if (! Value) {alert ('invalidvalue'); location. href = "/errors/invalid. php "rel =" external nofollow ";}} function toggleSelected (element) {if (hasClass (element, 'selected') {removeClass (element, 'selected ');} else {addClass (element, 'selected ');}}

The following code stores the configuration data in the config object. Each attribute of the config object stores a data segment with a prefix, indicates the data type (MSG indicates the information presented to the user, URL indicates the network address, CSS indicates a className ). Of course, you can also put the entire config object in a separate file, so that modifications to the configuration data can be completely isolated from the code using this data.

// Good practice var config = {MSG_INVALID_VALUE: 'invalidvalue', URL_INVALID: '/errors/Invalid. php ', CSS_SELECTED: 'selected'} function validate (value) {if (! Value) {alert (config. MSG_INVALID_VALUE); location. href = config. URL_INVALID ;}} function toggleSelected (element) {if (hasClass (element, config. CSS_SELECTED) {removeClass (element, config. CSS_SELECTED);} else {addClass (element, config. CSS_SELECTED );}}
Selector Optimization

Use the element selected by the selector as the static property of the object to centrally manage it in one place.

initializeElements: function() {  var eles = app.Eles;  for (var name in eles) {    if (eles.hasOwnProperty(name)) {      this[name] = $(eles[name]);    }  }}

The following is an example.

// Good practice app. eles = {widgetDiv :". left-widget div ", inputResize :'. input-resize ', hr :'. hr ', txt :'. input-group-btn button ', cus:' # paper-type-cuts', hid: '# Den den', mainCon: '# mainCon', rulerX :'. rery-x', rulerY :'. raudio-y ',};
Function Optimization

[Extraction function]

In javascript development, I have been dealing with functions most of the time, so I hope these functions are well named and the logic contained in the functions is clear and clear. If a function is too long and requires some comments to make it easier to read, it is necessary to refactor these functions.

If a piece of code in a function can be independent, it is best to put the code into another independent function. This is a very common optimization work. The main benefits of doing so are as follows:

1. Avoid super-large Functions

2. Independent functions help code reuse

3. Independent functions are more likely to be overwritten.

4. if an independent function has a good name, it plays the role of annotation.

For example, in a function that obtains user information, you need to print logs related to user information. Then, the log printing statement can be encapsulated in an independent function:

Var getUserInfo = function () {ajax ('HTTP: // xxx.com/userInfo', function (data) {console. log ('userid: '+ data. userId); console. log ('username: '+ data. userName); console. log ('nickname: '+ data. nickName) ;};}; // changed to var getUserInfo = function () {ajax ('HTTP: // xxx.com/userInfo', function (data) {printDetails (data) ;}) ;}; var printDetails = function (data) {console. log ('userid: '+ data. userId); console. log ('username: '+ data. userName); console. log ('nickname: '+ data. nickName );};

[Minimize the number of parameters]

If you need to input multiple parameters when calling a function, this function is daunting. You must understand the meaning of these parameters and carefully import them to the function in order. In actual development, it is inevitable to pass parameters to the function, but the number of parameters received by the function should be minimized. The following is a simple example. There is a drawing function draw, which can only draw squares and receives three parameters: width, heigth, and square:

var draw = function(width,height,square){};

But in fact, the square area can be calculated by width and height, so we can remove the square parameter from the draw function:

var draw = function( width, height ){  var square = width * height;};

Assume that the draw function will support circular drawing in the future. You need to replace the width and height parameters with the radius, but the area square of the image should never be input by the customer, but should be inside the draw function, calculated based on the input parameters plus certain rules. In this case, you can use the policy mode to make the draw function a function that supports drawing multiple types of images.

[Transfer object parameters to replace the list of too long parameters]

Sometimes a function may receive multiple parameters. The more parameters a function has, the more difficult it is to understand and use them. When using this function, you must first understand the meaning of all parameters, and be careful when using it to avoid missing a parameter or reversing the two parameters. If you want to add a new parameter to the 3rd and 4th parameters, many code modifications are involved. The Code is as follows:

var setUserInfo = function( id, name, address, sex, mobile, qq ){  console.log( 'id= ' + id );  console.log( 'name= ' +name );  console.log( 'address= ' + address );  console.log( 'sex= ' + sex );  console.log( 'mobile= ' + mobile );  console.log( 'qq= ' + qq );};setUserInfo( 1314, 'xiaohuochai', 'beijing', 'male', '150********', 121631835 );

In this case, you can put all the parameters in an object, and then pass the object into the setUserInfo function. The data required by the setUserInfo function can be obtained from this object by yourself. Now you don't have to worry about the number and order of parameters. You just need to ensure that the key value corresponding to the parameter remains the same:

var setUserInfo = function( obj ){    console.log( 'id= ' + obj.id );    console.log( 'name= ' + obj.name );    console.log( 'address= ' + obj.address );    console.log( 'sex= ' + obj.sex );    console.log( 'mobile= ' + obj.mobile );    console.log( 'qq= ' + obj.qq );  };  setUserInfo({    id: 1314,    name: 'xiaohuochai',    address: 'beijing',    sex: 'male',    mobile: '150********',    qq: 121631835  });
Condition Optimization

Merge condition fragments]

If a function contains some conditional branch statements that contain repeated code, merge them to remove them. Assume that there is a paging function paging, which receives a parameter currPage, which indicates the page number to jump. Before the jump, to prevent the currPage from passing in a small or too large number, you must manually correct its value. For details, see the following pseudocode:

Var paging = function (currPage) {if (currPage <= 0) {currPage = 0; jump (currPage); // jump} else if (currPage> = totalPage) {currPage = totalPage; jump (currPage); // jump} else {jump (currPage); // jump }};

As you can see, the jump code jump (currPage) appears in each condition branch, so you can completely separate the Code:

Var paging = function (currPage) {if (currPage <= 0) {currPage = 0;} else if (currPage> = totalPage) {currPage = totalPage;} jump (currPage ); // separate the jump function };

[Extract the condition branch statement into a function]

In program design, complicated conditional branch statements are an important reason for the program to be difficult to read and understand, and can easily lead to a large function. Assume that one requirement is to compile a getPrice function to calculate the commodity price. There is only one rule for commodity calculation: if it is in the summer, all commodities will be sold at a discount. The Code is as follows:

Var getPrice = function (price) {var date = new Date (); if (date. getMonth ()> = 6 & date. getMonth () <= 9) {// return price * 0.8 in summer;} return price ;};

Observe this Code:

date.getMonth()>=6&&date.getMonth()<=9

The meaning of this code is very simple, that is, to determine whether the current is in the summer (7 ~ October ). Although the Code is very short and small, there are still some distance between the intent expressed by the Code and the Code itself. It is necessary for people who read the code to spend more time understanding the intent it conveys. In fact, the code can be extracted into a separate function, which can more accurately express the meaning of the code, and the function name itself can play a role in commenting. The Code is as follows:

Var isSummer = function () {var date = new Date (); return date. getMonth ()> = 6 & date. getMonth () <= 9 ;}; var getPrice = function (price) {if (isSummer () {// return price * 0.8 in summer;} return price ;};

[Exit the function in advance to replace the nested condition branch]

Many programmers have the idea that "each function can have only one entry and one exit ." Modern Programming Languages limit that functions have only one entry. However, there are usually some different opinions on "functions have only one exit. The following pseudocode is a typical code that complies with "the function has only one exit:

Var del = function (obj) {var ret; if (! Obj. isReadOnly) {// if (obj. isFolder) {// if the folder ret = deleteFolder (obj);} else if (obj. isFile) {// if the file ret = deleteFile (obj) ;}} return ret ;};

Nested conditional branch statements are definitely the nightmare of code maintainers. For those who read the code, nested if and else statements are more difficult to read and understand than tiled if and else statements. Nested condition branches are often written by programmers who believe that "each function can only have one exit. But in fact, if you are not interested in the rest of the function, you should exit immediately. Guiding readers to see useless else fragments only hinders their understanding of the program

Therefore, you can select some condition branches and immediately exit the function after entering these condition branches. To do this, there is a common technique, that is, when facing a nested if branch, the outer if expression can be reversed. The reconstructed del function is as follows:

Var del = function (obj) {if (obj. isReadOnly) {// reverse the if expression return;} if (obj. isFolder) {return deleteFolder (obj);} if (obj. isFile) {return deleteFile (obj );}};
Loop Optimization

[Rational use cycle]

In the function body, if some code is actually responsible for some repetitive work, the rational use of loops can not only complete the same function, but also reduce the amount of code. The following code creates an XHR object. to simplify the example, only Internet Explorer versions earlier than 9 are considered. The Code is as follows:

var createXHR = function(){  var xhr;  try{    xhr = new ActiveXObject( 'MSXML2.XMLHttp.6.0' );  }catch(e){    try{      xhr = new ActiveXObject( 'MSXML2.XMLHttp.3.0' );    }catch(e){      xhr = new ActiveXObject( 'MSXML2.XMLHttp' );    }  }  return xhr;};var xhr = createXHR();

The following flexible use of the loop can achieve the same effect as the above Code:

// Below we use the loop flexibly to get the same effect as the above Code: var createXHR = function () {var versions = ['msxml2. XMLHttp.6.0ddd ', 'msxml2. XMLHttp.3.0 ', 'msxml2. XMLHttp ']; for (var I = 0, version; version = versions [I ++];) {try {return new ActiveXObject (version);} catch (e) {}}; var xhr = createXHR ();

[Exit multiple cycles with return]

Assume that there is a two-loop statement in the function body, which needs to be determined in the internal loop. When a critical condition is reached, the function exits the outer loop. Most of the time, a control tag variable is introduced:

var func = function(){  var flag = false;  for ( var i = 0; i < 10; i++ ){    for ( var j = 0; j < 10; j++ ){      if ( i * j >30 ){        flag = true;        break;      }    }    if ( flag === true ){      break;    }  }};

The second method is to set the loop Tag:

var func = function(){  outerloop:  for ( var i = 0; i < 10; i++ ){    innerloop:    for ( var j = 0; j < 10; j++ ){      if ( i * j >30 ){        break outerloop;      }    }  }};

These two methods are undoubtedly dizzy, and the simpler method is to exit the entire method directly when the loop needs to be terminated:

var func = function(){  for ( var i = 0; i < 10; i++ ){    for ( var j = 0; j < 10; j++ ){      if ( i * j >30 ){        return;      }    }  }};

Of course, the direct exit method with return will bring about a problem. What if there is still some code to be executed after the loop? If you exit the entire method in advance, the Code cannot be executed:

Var func = function () {for (var I = 0; I <10; I ++) {for (var j = 0; j <10; j ++) {if (I * j> 30) {return ;}} console. log (I); // This code has no chance to be executed };

To solve this problem, you can put the code after the loop behind return. If there are many codes, you should extract them into a separate function:

var print = function( i ){  console.log( i );};var func = function(){  for ( var i = 0; i < 10; i++ ){    for ( var j = 0; j < 10; j++ ){      if ( i * j >30 ){        return print( i );      }    }  }};func();

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.