preface

These are the ones I’ve collected, used and JSBench tested on the web. If you have any more, feel free to leave them in the comments section

External manifestation of memory problems

  • Pages load lazily or pause frequently
  • The page continues to have poor performance
  • Page performance deteriorates over time

Criteria for defining memory problems

  • Memory leak: Memory usage continues to rise
  • Memory bloat: Performance issues on most devices
  • Frequent garbage collection: Analyzed by memory variation graph

The separation of the DOM

  • Interface elements live in the DOM tree
  • DOM node when garbage object
  • Separate state DOM nodes

TimeLine Record Memory-Performance panel

<! doctypehtml>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="Width =device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <button id="btn">new</button>

    <script>
        const arr = []

        function test () {
          for (let i = 0; i < 1000000; i++) {
            document.body.appendChild(document.createElement('p'))
          }
          arr.push(new Array(1000000).join('x'))}document.getElementById('btn').addEventListener('click', test)
    </script>
</body>
</html>
Copy the code

Heap map monitor Memory – Memory panel

<! doctypehtml>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="Width =device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <button id="btn">new</button>

    <script>
        const arr = []

        function test () {
          for (let i = 0; i < 1000000; i++) {
            document.body.appendChild(document.createElement('p'))
          }
          arr.push(new Array(1000000).join('x'))}document.getElementById('btn').addEventListener('click', test)
    </script>
</body>
</html>
Copy the code

How do I determine frequent garbage collection

  • Frequent ups and downs in Timeline
  • Frequent data increases and decreases in task manager

Performance optimization

Be careful with global variables

  • Global variables are defined in the global execution context and are at the top of any scope chain
  • The global execution context remains in the context execution stack until the program exits
  • The presence of a variable with the same name in a local scope obscures or contaminates the whole world
// Global variables
var i, str = ' '
for (i =0; i< 1000; i++) {
	str += i
}

// Local variables (faster)
for (let i =0; i< 1000; i++) {
	let str = ' '
	str += i
}
Copy the code

Caching global variables

  • Global variables that cannot be avoided in use are cached locally
// Non-cached
const obj = {
	name: 'jcode'.age: 18
}

function fn () {
	console.log(obj.name)
  console.log(obj.name)
  console.log(obj.name)
  console.log(obj.name)
  console.log(obj.name)
}

fn()


// Cache mode (faster)
const obj = {
	name: 'jcode'.age: 18
}

function fn () {
	const o = obj
  console.log(o.name)
  console.log(o.name)
  console.log(o.name)
  console.log(o.name)
}

fn()
Copy the code

Add by prototype

  • Methods needed to add an instance object to a prototype object
// Defined on the prototype instance
function Person () {
	this.sayHi = function () {
  	console.log('sayHi')}}const p1 = new Person()


// Define on prototype (faster)
function Person () {}
Person.prototype.sayHi = function () {
	console.log('sayHi')}const p1 = new Person()
Copy the code

Avoid closure traps

  • Each closure call destroys as many useless variables as possible
<! doctypehtml>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="Width =device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<button id="btn" class="dd">add</button>

<script>
    function foo () {
        var el = document.getElementById('btn')
        el.onclick = function () {
            console.log(el.id, el.className)
        }
        el = null

    }

    foo()
</script>
</body>
</html>
Copy the code

Avoid attribute access methods

  • Object orientation in JavaScript
    • JS does not require attribute access methods, all attributes are externally visible
    • Using attribute access methods only adds another layer of redefinition without access control
// Access attributes indirectly by defining methods (slow)
function Person () {
  this.name = 'jcode'
  this.age = 18
  this.getAge = function () {
    return this.age
  }
}

const p1 = new Person()
const a = p1.getAge()


// Access attributes directly (faster)
function Person () {
  this.name = 'jcode'
  this.age = 18
}
const p1 = new Person()
const b = p1.age
Copy the code

For loop optimization

var arr = [1.2.3.4.5.6.7]
for (var i = 0; i < arr.length; i++) {
	console.log(i)
}


/ / faster
var arr = [1.2.3.4.5.6.7]
for (var i = 0, len = arr.length; i < len; i++) {
	console.log(i)
}
Copy the code

For loop optimally sorts

  • ForEach (fastest) > for(optimized for) > for in

Node addition optimization

  • The addition of nodes inevitably involves backflow and redraw
for (var i = 0; i < 10; i++) {
	var oP = document.createElement('p')
  oP.innerHTML = i
  document.body.appendChild(oP)
}


// Document fragmentation adds (faster)
const fragEle = document.createDocumentFragment()
for (var i = 0; i < 10; i++) {
  var oP = document.createElement('p')
  oP.innerHTML = i
  fragEle.appendChild(oP)
}
document.body.appendChild(fragEle)
Copy the code

Clone optimized node operation

<! doctypehtml>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="Width =device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<p id="box1">old</p>

<script>
    for (var i =0; i < 5; i++) {
        var oP = document.createElement('p')
        oP.innerHTML = i
        document.body.appendChild(oP)
    }


    // Clone the way (faster)
    var oldP = document.getElementById('box1')
    for (var i =0; i < 5; i++) {
        var newP = document.cloneNode(false)
        newP.innerHTML = i
        document.body.appendChild(newP)
    }
</script>
</body>
</html>
Copy the code

Literal replacement for new Array

var arr = newArray(3)
arr[0] = 1
arr[1] = 2
arr[2] = 3

/ / faster
var arr = [1.2.3]
Copy the code

Reduce the level of judgment

  • Return as early as possible to end the statement
  • Switch provides better performance

Reduce the scope chain lookup level

Reduce the number of data reads

function (ele, cla) {
	return ele.className === cls
}


// Do a cache, faster
function (ele, cla) {
  let clsName = ele.className
	return clsName === cls
}
Copy the code

Literals and constructors – Literals are fast

  • The reference types are similar
  • The underlying data types vary considerably
const obj = new Object()
obj.name = 'jcode'


// The literal way is faster
const obj = {
  name: 'jcode'
}
Copy the code

Reduce circulatory body activity

  • Try to lift immutable operations out of the loop body
// Faster than the normal for loop
const test = () = > {
	var i
  var arr = [1.2.3]
  var len = arr.length
  for (i = 0; i < len; i++) {
    console.log(arr[i])
  }
}

/ / faster
const test = () = > {
  var arr = [1.2.3]
  var len = arr.length
  while (len--) {
    console.log(arr[len])
  }
}
Copy the code

Reduce the number of declarations and statements

var name = 'jcode'
var age = 19


/ / faster
var name = 'jcode',
    age = 19
Copy the code

Use event binding

Using event delegate

  <ul id="ul">
    <li>jcode</li>
    <li>18</li>
  </ul>
<script>
  var list = document.querySelectorAll('li')
  function showTxt (ev) {
    console.log(ev.target.innerHTML)
  }
  for(let item of list) {
    item.onclick = showTxt
  }
  // The following is more efficient
  var ul = document.getElementById('ul')
  ul.addEventListener('click', showTxt, true)
  function showTxt (ev) {
    var obj = ev.target
    if (obj.nodeName.toLowerCase() === 'li') {
      console.log(obj.innerHTML)
    }
  }
</script>
Copy the code

References:

Language finch: www.yuque.com/xixieguibug…