11 Javascript tips to help you improve code quality of summary
- 2021-10-16 00:41:53
- OfStack
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 stateThe 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