11 Javascript tips to help you improve code quality of summary

  • 2021-10-16 00:41:53
  • OfStack

Catalog 1. Extract functions
2. Merge duplicate conditional fragments
3. Reduce conditional branching statements into functions
4. Rational use of cycles
5. Exit functions early instead of nested conditional branches
6. Pass object parameters instead of an overly long parameter list
7. Use less 3-entry operators
8. Reasonable use of chain calls
9. Decompose large classes
10. Flexible Bit Operators
11. Pure functions
Reference

This article will be updated constantly, and the shortcomings are welcome to be added in the comment area.

1. Extract the function

Benefits:

Avoid oversized functions. Independent functions help code reuse. Stand-alone functions are easier to override. If a stand-alone function has a good name, it itself plays the role of annotation. Semantics puts multiple pieces of separated logic into different functions, which can make the code logic clear and clearly see what each step is doing.

Code example:

Implementation gets the data, then manipulates dom to display the data, and finally adds an event

Before function refinement


//  Logic is written in 1 From now on, you need to read all the logic before you know what this code is. Local logic cannot be reused 
function main() {
 $.ajax.get('/getData').then((res) => {
  const ul = document.getElementById('ul');
  ul.innerHTML = res.list.map(text => `<li class="li">${text}</li>`).join('\n');
  const list = document.getElementsByClassName('li');
  for (let i = 0; i < list.length; i ++) {
   list[i].addEventListener('focus', () => {
    // do something
   });
  }
 });
}

After function refinement


function getData() {
 return $.ajax.get('/getData').then((res) => res.data.list);
}
function showList(list) {
 const ul = document.getElementById('ul');
 ul.innerHTML = list.map(text => `<li class="li">${text}</li>`).join('\n');
}
function addEvent() {
 const list = document.getElementsByClassName('li');
 for (let i = 0; i < list.length; i ++) {
  list[i].addEventListener('focus', () => {
   // do something
  });
 }
}
//  Clear logic, 1 Eye reading every 1 What are you doing? Some of the extracted functions can also be reused 
async function main() {
 const list = await getData(); //  Get data 
 showList(list); //  Display page 
 addEvent(); //  Add Events 
}

2. Merge duplicate conditional fragments

If there are 1 conditional branch statements in a function body, and 1 duplicate code is scattered inside these conditional branch statements, it is necessary to merge and remove duplicates.


//  Before merging 
function main( currPage ){
 if ( currPage <= 0 ){
  currPage = 0;
  jump( currPage ); //  Jump 
 }else if ( currPage >= totalPage ){
  currPage = totalPage;
  jump( currPage ); //  Jump 
 }else{
  jump( currPage ); //  Jump 
 }
};

//  After the merger 
function main( currPage ){
 if ( currPage <= 0 ){
  currPage = 0;
 }else if ( currPage >= totalPage ){
  currPage = totalPage;
 }
 jump( currPage ); //  Put jump  Function independence 
};

3. Reduce conditional branching statements into functions

Complex conditional branching statements are an important reason why programs are difficult to read and understand, and it is easy to lead to a huge function. Sometimes conditional branch statements can be refined into semantic functions, which makes the code more intuitive and logical.


//  Determine the discount strength according to different seasons 
function getPrice( price ){
 var date = new Date();
 if ( date.getMonth() >= 6 && date.getMonth() <= 9 ){ //  Summer 
  return price * 0.8;
 }
 return price;
};


//  Is it summer 
function isSummer(){
 var date = new Date();
 return date.getMonth() >= 6 && date.getMonth() <= 9;
};
//  After refining conditions 
function getPrice( price ){
 if ( isSummer() ){
  return price * 0.8;
 }
 return price;
};

4. Rational use of cycles

If multiple pieces of code are actually responsible for repetitive work, you can use loops instead to make the amount of code less.


//  Determine what browser it is 
function getBrowser(){
 const str = navigator.userAgent;
 if (str.includes('QQBrowser')) {
 return 'qq';
 } else if (str.includes('Chrome')) {
 return 'chrome';
 } else if (str.includes('Safari')) {
  return 'safri';
 } else if (str.includes('Firefox')) {
  return 'firefox';
 } else if(explorer.indexOf('Opera') >= 0){
  return 'opera';
 } else if (str.includes('msie')) {
  return 'ie';
 } else {
  return 'other';
 }
};


//  Cyclic judgment abstracts the corresponding relationship into configuration, which is clearer and clearer 
function getBrowser(){
 const str = navigator.userAgent;
 const list = [
  {key: 'QQBrowser', browser: 'qq'},
  {key: 'Chrome', browser: 'chrome'},
  {key: 'Safari', browser: 'safari'},
  {key: 'Firefox', browser: 'firefox'},
  {key: 'Opera', browser: 'opera'},
  {key: 'msie', browser: 'ie'},
 ];
 for (let i = 0; i < list.length; i++) {
  const item = list[i];
  if (str.includes(item.key)) {return item.browser};
 }
 return 'other';
}

5. Exit functions early instead of nested conditional branches

Let the function return early with multiple exits, replacing nested conditional branches.


function del( obj ){
 var ret;
 if ( !obj.isReadOnly ){ //  It can only be deleted if it is not read-only 
  if ( obj.isFolder ){ //  If it is a folder 
   ret = deleteFolder( obj );
  }else if ( obj.isFile ){ //  If it is a file 
   ret = deleteFile( obj );
  }
 }
 return ret;
};

function del( obj ){
 if ( obj.isReadOnly ){ //  Reversal if  Expression 
  return;
 }
 if ( obj.isFolder ){
  return deleteFolder( obj );
 }
 if ( obj.isFile ){
  return deleteFile( obj );
 }
};

6. Pass object parameters instead of an overly long parameter list

If the function parameters are too long, it will increase the risk of errors. It is a troublesome thing to ensure that the order of transmission is correct, and the readability of the code will become worse. Try to ensure that the parameters of the function will not be too long. If multiple parameters must be passed, it is recommended to use objects instead.

1 Generally speaking, it is best to have no more than 3 parameters for a function


function setUserInfo( 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, 'sven', 'shenzhen', 'male', '137********', 377876679 );

function setUserInfo( 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: 'sven',
 address: 'shenzhen',
 sex: 'male',
 mobile: '137********',
 qq: 377876679
});

7. Use less 3-entry operators

3-mesh operator has high performance and less code.
However, we should not abuse the 3-item operator. We should use it in simple logic branches and avoid using it in complex logic branches.


//  Simple logic can be used 3 Destination operator 
var global = typeof window !== "undefined" ? window : this;

//  Complex logic is not suitable for use 
var ok = isString ? (isTooLang ? 2 : (isTooShort ? 1 : 0)) : -1;

8. Reasonable use of chain calls

Advantages:
Chain call is simple to use and has less code.

Disadvantages:
The disadvantage of chain call is that it is inconvenient to debug. If we know that there is an error in a chain, we must disassemble the chain before adding a debug log or adding breakpoints, so as to locate the error.

If the structure of the chain is relatively stable and is not easy to be modified in the later period, the chain type can be used.


var User = {
 id: null,
 name: null,
 setId: function( id ){
  this.id = id;
  return this;
 },
 setName: function( name ){
  this.name = name;
  return this;
 }
};
User
 .setId( 1314 )
 .setName( 'sven' );

var user = new User();
user.setId( 1314 );
user.setName( 'sven' );

9. Decompose large classes

The decomposition of large-scale classes is very similar to the refinement of functions. If the classes are too large, the logic is unclear, and it is difficult to understand and maintain them.
Reasonable decomposition of large classes can make the logic of classes clear, and sub-modules can be easily reused.

10. Flexible Bit Operators

Programming languages do not perform well in computing multiplication and division, but in some cases, using bit operators can improve the performance of operations such as multiplication and division.

11. Pure functions

A pure function is a function that does not depend on and does not change the state of variables outside its scope.
The return value of a pure function is determined only by the parameters when it is called, and its execution does not depend on the state of the system (execution context).
With the same input parameters, 1 will get the same output, that is, it does not contain random variables that will affect the output.

Characteristics that are not pure functions:

Change the file system Insert records into the database Send 1 http request Variable data Print/log Get user input DOM Query Access system state

The role of pure functions:

Reliability: The function returns forever and expected 1 Caching ability: As long as one sample is input and one sample is output, the input can be used as key and the output can be used as a value, and the calculated results can be cached by using objects Portability: Porting to any environment works correctly because there are no external dependencies Testability: Convenient unit testing for functions Parallelism: For 1 complex computation, parallel computation (for example, using nodejs multiple sub-processes to compute multiple tasks in parallel at the same time, improve the computation speed)

Application scenario:

It is best to use pure functions for tool functions Codes used by multiple platforms (nodejs, browser, WeChat applet, native client, etc.) Relatively independent functions

var a = 1;
//  Impure function 
function sum(b) {
 return a + b;
}
//  Impure function 
function sum(b) {
 a = 2;
 return b;
}
//  Impure function 
function sum(b) {
 return b + Math.random();
}


//  Pure function 
function sum (b, c) {
 return b + c;
}

Reference

Design Pattern and Development Practice of JavaScript


Related articles: