How to write high-quality JavaScript code

How to write high-quality JavaScript code

A while ago, a video called "Human High Quality Male" became popular. I believe many students have seen it. So today I want to share with you what "human-quality code" is. Haha, just kidding.

In fact, what I share are some small tricks that I have summarized in my daily life. I hope they can bring some inspiration and help to everyone.

How to write high-quality JavaScript code? Let’s study the following article together

1. Easy to read code

First of all, the code is written for yourself or team members to read, and a good reading method is a prerequisite for writing high-quality code. Here are four specific operation methods summarized to share with you.

1. Unified code format

Don’t write one way sometimes and another way sometimes. Try to keep your writing consistent. Here is an example.

//bad
function foo(x,y) {
  return {
    sum : x + y
  };
}
function bar(m, n){
  let ret = m*n
  return ret;
}
//good
function foo(x, y) { // Separate with appropriate spaces. Generally, no spaces are added before symbols, but spaces are added after symbols. return {
    sum: x + y, // Trailing commas are legal, simplifying adding or removing elements from objects and arrays} // Omit the closing semicolon, but you need to know how to avoid the risk}
function bar(m, n) {
  let ret = m * n
  return ret
}


It is inconvenient to agree on the code format manually, so you can use some tools to automatically convert the format, such as: prettier plug-in (https://prettier.io/).

2. Remove magic numbers

magic number is a specific numerical value written directly in the program code in programming (such as "10", "123", etc.) Although the programmer can understand the meaning of the value when writing the program, it will be difficult for other programmers, or even the programmer himself, to understand the purpose of the value after a period of time.

//bad
setTimeout(blastOff, 86400000)
document.onkeydown = function (ev) {
  if (ev.keyCode === 13) {
    // todos
  }
}
//good
const MILLISECONDS_IN_A_DAY = 86400000
const ENTER_KEY = 13
setTimeout(blastOff, MILLISECONDS_IN_A_DAY)
document.onkeydown = function (ev) {
  if (ev.keyCode === ENTER_KEY) {
    // todos
  }
}


Of course, magic strings are also handled in the same way as above. It is recommended to use underscores to name constants in the above code, and it is recommended to use camel case to name other variables and functions.

In fact, the same principle applies to reducing the frequency of using this. When the code is filled with a large number of this , it is often difficult for us to know who it is and it takes a lot of time to read it.

//bad
class Foo {
    foo() {
        this.number = 100
        this.el.onclick = function () {
            this.className = "active"
        }
    }
}
//good
class Foo {
    foo() {
        let context = this
        context.number = 100
        context.el.onclick = function () {
            let el = this
            el.className = "active"
        }
    }
}

3. Single Function Principle

Whether you are writing modules, classes, or functions, they should each have a single function and not do too many things. This will make it very easy to read and very flexible to expand.

//bad
function copy(obj, deep) {
  if (deep) {
    //deep copy} else {
    // Shallow copy}
}
//good
function copy(obj) {
  // Shallow copy}
function deepCopy(obj) {
  // deep copy}

4. Reduce the number of nesting levels

Multi-level nesting, such as conditional nesting, loop nesting, callback nesting, etc., is very unfavorable for code reading, so the nesting level should be reduced as much as possible.

To solve the problem of nested conditions, guard clause can generally be used to return early, thereby reducing nesting.

//bad
function foo() {
  let result
  if (isDead) {
    result = deadAmount()
  } else {
    if (isRet) {
      result = retAmount()
    } else {
      result = normalAmount()
    }
  }
  return result
}
//good
function foo() {
  if (isDead) {
    return deadAmount()
  }
  if (isRet) {
    return retAmount()
  }
  return normalAmount()
}

In addition to guard statements, conditional statements can also be rewritten using short-circuit operations, conditional operators, etc.

//bad
function foo() {
    if (isOk) {
        todo()
    }
    let grade
    if (isAdmin) {
        grade = 1
    } else {
        grade = 0
    }
}
//good
function foo() {
    isOk && todo() // short-circuit operation let grade = isAdmin ? 1 : 0 // conditional operator }

To solve the problem of nested callbacks, you can generally rewrite it using the " async/await " method.

//bad
let fs = require("fs")
function init() {
  fs.mkdir(root, (err) => {
    fs.mkdir(path.join(root, "public", "stylesheets"), (err) => {
      fs.writeFile(
        path.join(root, "public", "stylesheets", "style.css"),
        "",
        function (err) {}
      )
    })
  })
}
init()
//good
let fs = require("fs").promises
async function init() {
  await fs.mkdir(root)
  await fs.mkdir(path.join(root, "public", "stylesheets"))
  await fs.writeFile(path.join(root, "public", "stylesheets", "style.css"), "")
}
init()

In addition to the four suggestions introduced above, there are many other points that can improve the reading experience, such as: effective annotations, avoiding different types of comparisons, avoiding awkward grammar, etc.

2. High-performance code

In software development, the performance of the code will directly affect the user experience of the product, so high-quality code must have high performance. Here are four specific operation methods summarized to share with you.

Tip: To test the average time taken by JavaScript , you can use console.time() method, JSBench.Me tool, performance tool, etc.

1. Optimization algorithm

Recursion is a common algorithm. The following is an operation of "finding factorial" implemented using recursion.

//bad
function foo(n) {
  if (n === 1) {
    return 1
  }
  return n * foo(n - 1)
}
foo(100) // Average time: 0.47ms
//good
function foo(n, result = 1) {
  if (n === 1) {
    return result
  }
  return foo(n - 1, n * result) // tail call optimization here}
foo(100) // Average time: 0.09ms


"Tail call" is a memory management optimization mechanism that can reuse stack frames, that is, the return value of an external function is the return value of an internal function.

2. Use built-in methods

Many functions can be solved by using JavaScript built-in methods. Often the underlying implementation of the built-in methods is optimal, and the built-in methods can be executed in advance in the interpreter, so the execution efficiency is very high.

The following example shows how to obtain the composite array form of object attributes and values.

//bad
let data = {
  username: "leo",
  age: 20,
  gender: "male",
}
let result = []
for (let attr in data) {
  result.push([attr, data[attr]])
}
console.log(result)
//good
let data = {
  username: "leo",
  age: 20,
  gender: "male",
}
let result = Object.entries(data)
console.log(result)

3. Reduce scope chain lookups

The scope chain is the implementation of the scope rule. Through the implementation of the scope chain, variables can be accessed within its scope and functions can be called within its scope. The scope chain is a linked list that can only be accessed in one direction. Each node on this linked list is the variable object of the execution context (the active object when the code is executed). The head of the one-way linked list (the first node that can be accessed) is always the variable object (active object) of the function currently being called and executed, and the tail is always the global active object.

If the concept is too complicated, take a look at the picture below.

The scope chain is 3 (head: bar) -> 2 (foo) -> 1 (tail: global), so when looking up variables, you should try to complete the acquisition at the head, so that you can save performance . The specific comparison is as follows.

//bad
function foo() {
  $("li").click(function () { // Global search once$("li").hide() // Global search again$(this).show()
  })
}
//good
function foo() {
  let $li = $("li") // Reduce the scope search level of $li below $li.click(function () {      
    $li.hide()               
    $(this).show()
  })
}


In addition to reducing scope chain lookups, the same principle applies to reducing object property lookups.

//bad
function isNull(arg) {
  return Object.prototype.toString.call(arg) === "[object Null]"
}
function isFunction(arg) {
  return Object.prototype.toString.call(arg) === "[object Function]"
}
//good
let toString = Object.prototype.toString
function isNull(arg) {
  return toString.call(arg) === "[object Null]"
}
function isFunction(arg) {
  return toString.call(arg) === "[object Function]"
}

4. Avoid duplicating code

Sometimes when writing a program, there will be a lot of repetitive code, and it is best to avoid doing repetitive operations. Let's take a simple example and find the index position of the first element that meets the conditions through a loop.

//bad
let index = 0
for (let i = 0, len = li.length; i < len; i++) {
    if (li[i].dataset.switch === "on") {
        index = i
    }
}
//good
let index = 0
for (let i = 0, len = li.length; i < len; i++) {
    if (li[i].dataset.switch === "on") {
        index = i
        break // The following loop is meaningless and executes unnecessary code}
}


Let’s look at another case of calculating the “Fibonacci sequence”.

//bad
function foo(n) {
  if (n < 3) {
    return 1
  }
  return foo(n - 1) + foo(n - 2)
}
foo(40) // Average time: 1043ms
//good
let cache = {}
function foo(n) {
  if (n < 3) {
    return 1
  }
  if (!cache[n]) {
    cache[n] = foo(n - 1) + foo(n - 2)
  }
  return cache[n]
}
foo(40) // Average time: 0.16ms


Here, the results of recursive execution are cached in an array, so that the next repeated code can directly read the data in the cache, thereby greatly improving performance.

The cross-marked part will be cached and the calculation will not be repeated.

In addition to the four suggestions introduced above, there are many other points that can improve code performance, such as: reducing DOM operations, throttling processing, event delegation, etc.

3. Robust Code

The so-called robust code is the code that is written to be extensible, maintainable, and testable. Here are four specific operation methods summarized to share with you.

1. Use new syntax

Many new syntaxes can make up for the bugs in previous syntaxes, making the code more robust and future-proof.

//bad
var a = 1
isNaN(NaN) // true
isNaN(undefined) // true
//good
let a = 1
Number.isNaN(NaN) // true
Number.isNaN(undefined) // false


The new syntax can also simplify previous operations and make the code structure clearer.

//bad
let user = { name: "james", age: 36 }
function foo() {
  let arg = arguments
  let name = user.name
  let age = user.age
}
//good
let user = { name: "james", age: 36 }
function foo(...arg) { // rest parameters let { name, age } = user // destructuring assignment }

2. Expandable at any time

Since product requirements are always subject to new changes, high requirements are placed on the scalability of the software, so robust code is code that can be adjusted at any time.

//bad
function foo(animal) {
  if (animal === "dog" || animal === "cat") {
    // todos
  }
}
function bar(name, age) {}
bar("james", 36)
//good
function foo(animal) {
  const animals = ["dog", "cat", "hamster", "turtle"] // Expandable matching value if (animals.includes(animal)) {
    // todos
  }
}
function bar(options) {} // can extend any parameter bar({
  gender: "male",
  name: "james",
  age: 36,
})

3. Avoid side effects

When a function performs some behavior other than taking a value and returning a result, it has a side effect. Side effects are not necessarily harmful, but if they are caused without restraint in a project, the possibility of code errors will be very high.

It is recommended not to modify global variables or mutable objects, and to complete requirements through parameters and return . Making the function pure also makes the code easier to test.

//bad
let fruits = "Apple Banana"
function splitFruits() {
  fruits = fruits.split(" ")
}
function addItemToCart(cart, item) {
  cart.push({ item, data: Date.now() })
}
//good
let fruits = "Apple Banana"
function splitFruits(fruits) {    
  return fruits.split(" ")
}
function addItemToCart(cart, item) {
  return [...cart, { item, data: Date.now() }]
}

4. Integrate logical concerns

When a project is too complex, various logics are often mixed together, which is very unfavorable for subsequent expansion and also affects the understanding of the code. Therefore, try to extract related logic together and manage it in a centralized manner. Like hooks in React and Composition API in Vue3 , they all adopt this idea.

//bad
export default {
  name: 'App',
  data(){
    return {
      searchHot: [],
      searchSuggest: [],
      searchHistory: [],
    },
    mounted() {
      // todo hot
      
      // todo history
    },
    methods: {
      handleSearchSuggest(){
        // todo suggest
      },
      handleSearchHistory(){
        // todo history
      }
    }
  }
}
//good
export default {
  name: "App",
  setup() {
    let { searchHot } = useSearchHot()
    let { searchSuggest, handleSearchSuggest } = useSearchSuggest()
    let { searchHistory, handleSearchHistory } = useSearchHistory()
    return {
      searchHot,
      searchSuggest,
      searchHistory,
      handleSearchSuggest,
      handleSearchHistory,
    }
  }
}
function useSearchHot() {
  // todo hot
}
function useSearchSuggest() {
  // todo suggest
}
function useSearchHistory() {
  // todo history
}


In addition to the four suggestions introduced above, there are many other points that can improve the robustness of the code, such as: exception handling, unit testing, using TS instead of JS, etc.

Finally, let’s summarize how to write high-quality JavaScript code:


This is the end of this article on how to write high-quality JavaScript code. For more relevant content on writing high-quality JavaScript code, please search for previous articles on 123WORDPRESS.COM or continue to browse the related articles below. I hope everyone will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • 12 ways to write high-quality JS code
  • The essentials of writing high-quality JavaScript code
  • How to write high-quality JS code (continued)
  • How to write high-quality JS code
  • In-depth understanding of JavaScript learning notes (I) Writing high-quality code
  • Deep Understanding of JavaScript Series (1) The Basics of Writing High-Quality JavaScript Code

<<:  Perform data statistics on different values ​​of the same field in SQL

>>:  Example of building a Jenkins service with Docker

Recommend

How to solve the abnormal error ERROR: 2002 in mysql

Recently, an error occurred while starting MySQL....

Solve the problem of ifconfig being unavailable in docker

Recently, when I was learning docker, I found tha...

mysql workbench installation and configuration tutorial under centOS

This article shares the MySQL Workbench installat...

Example of using Vue built-in component keep-alive

Table of contents 1. Usage of keep-alive Example ...

Notes on upgrading to mysql-connector-java8.0.27

Recently, an online security scan found a vulnera...

JavaScript to achieve a simple carousel effect

What is a carousel? Carousel: In a module or wind...

Talking about Less and More in Web Design (Picture)

Less is More is a catchphrase for many designers....

CSS margin overlap and how to prevent it

The vertically adjacent edges of two or more bloc...

How to write HTML head in mobile device web development

Copy code The code is as follows: <head> &l...

Function overloading in TypeScript

Table of contents 1. Function signature 2. Functi...

Ten important questions for learning the basics of Javascript

Table of contents 1. What is Javascript? 2. What ...

Implementation of grayscale release with Nginx and Lua

Install memcached yum install -y memcached #Start...

Do you know the difference between empty value and null value in mysql

Preface Recently I found that my friend's met...

CSS to achieve fast and cool shaking animation effect

1. Introduction to Animate.css Animate.css is a r...