Javascript front-end optimization code

Javascript front-end optimization code

Optimization of if judgment

JavaScript conditional statements are inevitable in our daily development, but many times our code is not well written. A series of if-else or multiple nested judgments will make the code bloated. The following example is used for optimization.

Demand: There are now 4 products, namely mobile phones, computers, televisions, and game consoles. Of course, the prices displayed for each product are different.

1. The simplest method: if judgment

let commodity = {
  phone: 'mobile phone',
  computer: 'computer',
  television: 'television',
  gameBoy: 'Game console',
}

function price(name) {
  if (name === commodity.phone) {
    console.log(1999)
  } else if (name === commodity.computer) {
    console.log(9999)
  } else if (name === commodity.television) {
    console.log(2999)
  } else if (name === commodity.gameBoy) {
    console.log(3999)
  }
}
price('Mobile phone') // 9999

Disadvantages: The code is too long, and it is not friendly to maintain and read.

2. A better method: Switch

let commodity = {
  phone: 'mobile phone',
  computer: 'computer',
  television: 'television',
  gameBoy: 'Game console',
}
const price = (name) => {
  switch (name) {
    case commodity.phone:
      console.log(1999)
      break
    case commodity.computer:
      console.log(9999)
      break
    case commodity.television:
      console.log(2999)
      break
    case commodity.gameBoy:
      console.log(3999)
      break
  }
}
price('Mobile phone') // 9999

3. A better approach: Strategy pattern

The strategy pattern uses techniques and ideas such as combination, delegation, and polymorphism to effectively avoid multiple conditional selection statements. It provides perfect support for the open-closed principle, encapsulating algorithms in independent strategies, making them easy to switch, easy to understand, and easy to extend.

const commodity = new Map([
  ['phone', 1999],
  ['computer', 9999],
  ['television', 2999],
  ['gameBoy', 3999],
])

const price = (name) => {
  return commodity.get(name)
}
price('phone') // 1999

Optimizing includes

Includes is a new API added in ES7. Unlike indexOf, includes directly returns a Boolean value, while indexOf returns the index value. Both arrays and strings have includes methods.

Requirement: Let's implement an identity authentication method and return the corresponding verification result by passing in the identity ID

Traditional methods

function verifyIdentity(identityId) {
  if (identityId == 1 || identityId == 2 || identityId == 3 || identityId == 4) {
    return 'Your identity is legal, please pass! '
  } else {
    return 'Your identity is illegal'
  }
}

Includes optimization

function verifyIdentity(identityId) {
  if ([1, 2, 3, 4].includes(identityId)) {
    return 'Your identity is legal, please pass! '
  } else {
    return 'Your identity is illegal'
  }
}

for loop

In JavaScript, we can use for(), while(), for(in), and for(in) loops. In fact, among these three loops, for(in) has the worst efficiency because it needs to query the hash key, so it should be used as little as possible.

The for loop is the most traditional statement, which uses the variable i as an index to keep track of the location to access and operates on an array.

var arr = ['a', 'b', 'c']
for (var i = 0; i < arr.length; i++) {
  console.log(arr[i]) //The results are a, b, c in order
}

There is a problem with the above method: when the length of the array reaches one million, arr.length will have to be calculated one million times, which is quite performance-intensive. So the following methods can be used to improve it.

var arr = ['a', 'b', 'c']
for (var i = 0, length = arr.length; i < length; i++) {
  console.log(arr[i]) //The results are a, b, c in order
}

In this case, arr.length only needs to be calculated once, which optimizes performance.

for-in is generally used to traverse the properties of an object, but the properties need to be enumerable to be read. At the same time, for-in can also traverse the array, and when traversing the array, it traverses the subscript value of the array.

var obj = { 0: 'a', 1: 'b', 2: 'c' }
for (var key in obj) {
  console.log(key) //The results are 0, 1, 2 in sequence
}

var arr = ['a', 'b', 'c']
for (var key in a) {
  console.log(key) //The results are 0, 1, 2 in sequence
}

The for-of statement looks a bit like the for-in statement, but unlike the for-of statement, it cannot loop over objects, only over arrays.

var arr = ['a', 'b', 'c']
for (var value of arr) {
  console.log(value) // The results are a, b, c in order
}

for-of is a better way to loop over an array than for-in. for-of can be used to iterate members of any data structure that has an Iterator interface. It reads the key value directly. for-in needs to exhaustively enumerate all the properties of the object, including custom added properties. Moreover, the key of for-in is of String type, which requires a conversion process and is quite costly.

Therefore, try to avoid using for-in when looping arrays during the development process.

Array deduplication

Array deduplication is often encountered in actual development and data processing. There are many methods, which are not listed here one by one.

1. The most traditional method: use the indexOf subscript property of the array to query.

function unique4(arr) {
  var newArr = []
  for (var i = 0; i < arr.length; i++) {
    if (newArr.indexOf(arr[i]) === -1) {
      newArr.push(arr[i])
    }
  }
  return newArr
}
console.log(unique4([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]))
// [1, 2, 3, 5, 6, 7, 4]

2. Optimization: Use the Set method of ES6.

Set itself is a constructor used to generate a Set data structure. The Set function can accept an array (or other data structure with iterable interface) as a parameter for initialization. The Set object allows you to store any type of value, whether it is a primitive value or an object reference. It is similar to an array, but the member values ​​are unique and there are no duplicate values.

function unique4(arr) {
  return Array.from(new Set(arr)) // Use Array.from to convert the Set structure into an array}
console.log(unique4([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]))
// [1, 2, 3, 5, 6, 7, 4]

Arrow Functions

Arrow function expressions have a more concise syntax than function expressions. Therefore, it is recommended to use arrow functions in development. Especially in Vue projects, using arrow functions does not require reassigning a variable after changing this.

// Using functions
var arr = [5, 3, 2, 9, 1]
var arrFunc = arr.map(function (x) {
  return x * x
})
console.log(arrFunc)

// Using arrow functions var arr = [5, 3, 2, 9, 1]
var arrFunc = arr.map((x) => x * x)

It is important to note that arrow functions do not bind arguments, but instead use rest parameters...

// arguments cannot be used
let fun1 = (b) => {
  console.log(arguments)
}
fun1(2, 92, 32, 32) // Uncaught ReferenceError: arguments is not defined

// Using rest parameters let fun2 = (...c) => {
  console.log(c)
}
fun2(3, 82, 32, 11323) // [3, 82, 32, 11323]

Creation of Dom

When creating multiple DOM elements, first append the elements to DocumentFragment, and finally add DocumentFragment to the page uniformly.

Conventional methods;

for (var i = 0; i < 1000; i++) {
  var el = document.createElement('p')
  el.innerhtml = i
  document.body.appendChild(el)
}

Using DocumentFragment to optimize multiple appends

var frag = document.createDocumentFragment()
for (var i = 0; i < 1000; i++) {
  var el = document.createElement('p')
  el.innerhtml = i
  frag.appendChild(el)
}
document.body.appendChild(frag)

A better approach: use an innerHTML assignment instead of building a DOM element

var html = []
for (var i = 0; i < 1000; i++) {
  html.push('<p>' + i + '</p>')
}
document.body.innerHTML = html.join('')

Memory Leaks

Memory that is no longer used by system processes is not released in time, which is called a memory leak. When the memory usage increases, it may affect the system performance at best, or even cause the process to crash.

Causes of memory leaks

Global variables

1. Undeclared variables or variables created using this (this points to window) will cause memory leaks

function fn() {
  a = "Actually, I'm a global variable"
}
fn()

function fn() {
  this.a = "Actually, I'm a global variable"
}
fn()

Solution:

  • Avoid creating global variables
  • To use strict mode, add use strict to the top of your JavaScript file header or function.

2. In the Vue single-page application, the declared global variables are not cleared when switching pages

<template>
  <div id="home">
    This is the home page</div>
</template>

<script>
  export default {
    mounted() {
      window.test = {
        // Here, the DOM object name of this page is referenced in the global window object: 'home',
        node: document.getElementById('home')
      }
    }
  }
</script>

Solution: Dispose of the reference when the page is unloaded.

destroyed () {
  window.test = null // Dereference when the page is unloaded}

Closures

Cause of memory leak caused by closure: Closure can maintain local variables within the function and prevent them from being released.

function fn() {
  var a = "I'm a"
  return function () {
    console.log(a)
  }
}

Solution: Define the event handling function externally and release the closure, or delete the reference to DOM in the external function that defines the event handling function.

Timer or event monitoring

Because some pages in the project will inevitably need timers or event monitoring. However, if the timer is not cleared in a timely and reasonable manner when leaving the current page, it will cause confusion in business logic or even application freezing. At this time, it is necessary to clear the timer event listener, that is, clear the timer in the life cycle function of page unloading (closing).

methods:{
  resizeFun () {
    this.tableHeight = window.innerHeight - document.getElementById('table').offsetTop - 128
  },
  setTimer() {
    this.timer = setInterval(() => { })
  },
  clearTimer() {//Clear timer clearInterval(this.timer)
    this.timer = null
	}
},
mounted() {
  this.setTimer()
  window.addEventListener('resize', this.resizeFun)
},
beforeDestroy() {
  window.removeEventListener('resize', this.resizeFun)
  this.clearTimer()
}

Stabilization and Throttling

In the process of front-end development, we often need to bind some continuously triggered events, such as resize, scroll, mousemove, etc., but sometimes we do not want to execute functions so frequently during the continuous triggering of events. This is when anti-shake and throttling come into play.

Case 1: When searching remotely, data needs to be obtained dynamically through the interface. If the interface is requested every time the user inputs data, it will waste bandwidth and performance.

<Select :remote-method="remoteMethod">
    <Option v-for="item in temoteList" :value="item.value" :key="item.id">{{item.label}}</Option>
</Select>

<script>
function debounce(fn, wait) {
  let timeout = null
  return function () {
    if (timeout !== null) clearTimeout(timeout)
    timeout = setTimeout(fn, wait)
  }
}

export default {
  methods: {
    remoteMethod:debounce(function (query) {
        // to do ...
    }, 200),
  }
}
<script>

Case 2: When the scroll event is continuously triggered, the handle function is not executed immediately. When the scroll event is not triggered within 1000 milliseconds, the handle function is triggered once with a delay.

function debounce(fn, wait) {
  let timeout = null
  return function () {
    if (timeout !== null) clearTimeout(timeout)
    timeout = setTimeout(fn, wait)
  }
}
function handle() {
  console.log(Math.random())
}
window.addEventListener('scroll', debounce(handle, 1000))

Load js asynchronously

By default, the browser loads js scripts synchronously. When parsing HTML, it will stop when it encounters a <script> tag. It will continue parsing and rendering after the script is downloaded, parsed, and executed.

If the js file is large, it will take a long time to download, which can easily cause the browser to get blocked. The browser page will show a "white screen" effect, and the user will feel that the browser is "stuck" and unresponsive. At this point, we can let the js script load and execute asynchronously.

<script src="path/to/home.js" defer></script>
<script src="path/to/home.js" async></script>

In the above code, the <script> tag has defer and async attributes respectively. When the browser recognizes these two attributes, js will be loaded asynchronously. In other words, the browser will not wait for the script to be downloaded and executed before executing further, but will continue to execute further.

The difference between defer and async:

  • defer: DOM structure is completely generated, and other scripts are executed before it is executed (rendering is completed). When there are multiple defer scripts, they will be loaded and executed in the order in which they appear on the page.
  • async: Once the download is complete, the rendering engine will interrupt rendering, execute this script, and then continue rendering (executed after downloading). When there are multiple async scripts, there is no guarantee that they will be loaded and executed in the order in which they appear on the page.

The above is the details of the Javascript front-end optimization code. For more information about Javascript optimization, please pay attention to other related articles on 123WORDPRESS.COM!

You may also be interested in:
  • Optimizing JavaScript programs through loops
  • Implementation of js tail call optimization
  • A brief analysis of JavaScript asynchronous code optimization
  • Some suggestions on improving website performance using JavaScript (Part 1)
  • Suggestions on improving website performance with JavaScript (Part 2)
  • JS website performance optimization notes
  • Practical experience in improving website performance
  • Detailed explanation of the daily use and optimization techniques of images on the website
  • Using javascript to solve image scaling and optimization code
  • How to optimize images to improve website performance

<<:  Detailed explanation of the whole process of building a personal blog with nginx+WordPress

>>:  Three networking methods and principles of VMware virtual machines (summary)

Recommend

Pull-down refresh and pull-up loading components based on Vue encapsulation

Based on Vue and native javascript encapsulation,...

JS achieves five-star praise case

This article shares the specific code of JS to ac...

A brief analysis of the difference between FIND_IN_SET() and IN in MySQL

I used the Mysql FIND_IN_SET function in a projec...

Some problems that may be caused by inconsistent MySQL encoding

Stored procedures and coding In MySQL stored proc...

How to achieve centered layout in CSS layout

1. Set the parent container to a table and the ch...

Solve the problem that Docker pulls MySQL image too slowly

After half an hour of trying to pull the MySQL im...

vmware virtual machine ubuntu18.04 installation tutorial

Installation Steps 1. Create a virtual machine 2....

Implementation of Nginx+ModSecurity security module deployment

Table of contents 1. Download 2. Deployment 1.Ngi...

Analysis of the principles and usage of Linux hard links and soft links

In the Linux system, there is a kind of file call...

MySQL 8.0 New Features - Introduction to Check Constraints

Table of contents Preface Check Constraints Creat...

Analysis of the Principle of MySQL Index Length Limit

This article mainly introduces the analysis of th...

Getting Started Tutorial for Beginners ④: How to bind subdirectories

To understand what this means, we must first know ...

Detailed explanation of storage engine in MySQL

MySQL storage engine overview What is a storage e...