在日常书写js的过程中,我们要从每一行代码开始,去提升速度,优化性能。 我总结了日常代码的一些提升点,在代码大量执行的时候,注意这些,会在速度或性能上有所提升。
性能测试网站:
慎用全局变量
全局变量特点:
-
全局变量定义在全局执行上下文,是作用域的顶端,层级查找时间消耗大
-
全局上下文一直存在上下文执行栈,直到程序退出,不会被回收
-
如果局部作用域中定义同名变量,会导致全局变量被遮蔽或污染
优化点:
- 减少作用域链查找层级
// example1
let i
for (i = 0; i < 1000; i++) {
console.log(i)
}
// example2 -- fastest
for (let i = 0; i < 1000; i++) {
console.log(i)
}
缓存全局变量
- 对于不可避免的全局变量,可以对全局变量进行缓存
优化点:
- 减少了数据读取次数(但是消耗了空间)
// example1
function logInfo() {
for (let i = 0; i < 1000; i++) {
console.log(i)
}
}
logInfo()
// example2 - fastest
function logInfo() {
const log = console.log
for (let i = 0; i < 1000; i++) {
log(i)
}
}
logInfo()
在原型对象上新增实例对象需要的方法
- 原型对象中的方法是共享的,构造函数中的方法是单独存储的
// example1
let Fn1 = function () {
this.foo = function() {
console.log(1)
}
}
let fn2 = new Fn1()
// example2 - fastest
let Fn2 = function () {}
Fn2.prototype.foo = function() {
console.log(1)
}
let fn2 = new Fn2()
避开闭包的陷阱
特点:
-
外部具有指向内部的引用
-
外部作用域访问内部作用域的变量
缺点:
-
闭包使用不当容易出现内存泄漏
-
不要为了闭包而闭包
优化点:
- 合适的时候释放变量
// example 1
function foo () {
let el = document.getElementById('btn')
el.onclick = function() {
console.log(el.id)
}
}
// example 2 - better
function foo () {
let el = document.getElementById('btn')
el.onclick = function() {
console.log(el.id)
}
// 释放空间
el = null
}
避免属性访问方法的使用
-
JS不需要属性的访问方法,所以的属性都是外部可见的
-
使用属性访问方法只会增加一重定义,没有访问的控制力
// example1
function Person () {
this.name = 'jill'
this.age = 18
this.getAge = function () {
return this.age
}
}
const p1 = new Person()
const age = p1.getAge()
// example2 - fastest
function Person () {
this.name = 'jill'
this.age = 18
}
const p1 = new Person()
const age = p1.age
条件判断
1、对于明确条件分支可以用switch代替if-else
-
条件较少时if-else更易读,但代码量较大时,switch看起来明朗一点
-
大多数情况下switch要比if-else更快
2、确保最可能出现的条件放在首位
循环
优化for循环
1、缓存变量
<p class="btn">add</p>
<p class="btn">add</p>
<p class="btn">add</p>
<p class="btn">add</p>
// example1
const btns = document.getElementsByClassName('btn')
for (let i = 0; i < btns.length; i++) {
console.log(i)
}
// example2 - fastest
const btns = document.getElementsByClassName('btn')
for (let i = 0, len = btns.length; i < len; i++) {
console.log(i)
}
2、采用forEach循环方式
// example1- slower
const arr = [1, 3, 2, 4, 1]
for (let key in arr) {
console.log(key)
}
// example2- better
const arr = [1, 3, 2, 4, 1]
for(let i = 0, len = arr.length; i < len; i++) {
console.log(i)
}
// example3- fastest
const arr = [1, 3, 2, 4, 1]
arr.forEach((item, index) => {
console.log(index)
})
3、while循环更优
// example1
for (let i = 0; i < 10;i++) {
console.log(i)
}
// example2- fastest
let i = 0
while(i < 10) {
console.log(i)
i++
}
直接量替换new Object
- 使用字面量的方式代替构造式
// example1
const a = new Array(3) // 涉及函数调用,消耗更多一点
a[0] = 1
a[1] = 2
a[2] = 3
// example2- fastest
const a = [1, 2, 3]
文档碎片优化节点添加
- 减少回流重绘
// example1
for (var i = 0; i< 10; i++) {
var op = document.createElement('p')
op.innerHTML = i
document.body.appendChild(op)
}
// example2- fastest
const frgEle = document.createDocumentFragment()
for (var i = 0; i< 10; i++) {
var op = document.createElement('p')
op.innerHTML = i
frgEle.appendChild(op)
}
document.body.appendChild(frgEle)
克隆优化节点操作
- 克隆一个节点比创建一个节点速度更快
// example1
for (var i = 0; i< 3; i++) {
var op = document.createElement('p')
op.innerHTML = i
document.body.appendChild(op)
}
// example2- fastest
const oldEle = document.getElementById('box1')
for (var i = 0; i< 10; i++) {
var op = oldEle.cloneNode(false)
op.innerHTML = i
document.body.appendChild(op)
}