JavaScript代码优化(减少作用域链上的查找次数(函数尾调用、尾递归、全局查找)、使用原生方法、减少语句、减少页面重绘、使用事件委托)

目录

减少作用域链操作

避免全局查找

函数尾调用优化

函数尾递归优化

暂存变量

优化循环 

尽量使用原生方法

使用switch替代if-else

减少语句数

简化申明

 合并语句

使用数组和对象字面量

去除注释和空行

减少页面的重排(回流)和重绘

使用文档碎片减少DOM交互

多次样式改变属性合并

使用innerHTML

缓存多次使用的特殊属性

避免使用document.write

减少drawImage

其它非代码方面

事件优化

使用事件委托

TOUCH事件优化

高频事件优化

其它

多条字符串拼接

 避免空的图片src


减少作用域链操作

避免全局查找

函数作用域中如果多次使用全局变量,则应该用局部变量保存全局变量的引用,避免反复通过作用域查找全局变量

function demo() {
    var imgs = document.getElementByTagName("img");  //获取页面所有img标签
     for(var i = 0; i <= imgs.length; i++) {
        imgs[i].title = document.title + "image" + i;
     }
    //上面for循环中反复使用document,这里应该添加局部变量代替document,应使用下面优化代码
    //for(var i = 0; i <= imgs.length; i++) {
    //   imgs[i].title = doc.title + "image" + i;
    //}
}

函数尾调用优化

函数调用会在内存形成一个“调用记录”,又称“调用帧”(call frame),保存调用位置和内部变量等信息。如果在函数A的内部调用函数B,那么在A的调用帧上方,还会形成一个B的调用帧。等到B运行结束,将结果返回到AB的调用帧才会消失。如果函数B内部还调用函数C,那就还有一个C的调用帧,以此类推。所有的调用帧,就形成一个“调用栈”(call stack)。

尾调用由于是函数的最后一步操作,所以不需要保留外层函数的调用帧,因为调用位置、内部变量等信息都不会再用到了,只要直接用内层函数的调用帧,取代外层函数的调用帧就可以了。

function f() {
  let m = 1;
  let n = 2;
  return g(m + n);
}
f();
// 等同于
function f() {
  return g(3);
}
f();
// 等同于
g(3);

上面代码中,如果函数g不是尾调用,函数f就需要保存内部变量mn的值、g的调用位置等信息。但由于调用g之后,函数f就结束了,所以执行到最后一步,完全可以删除f(x)的调用帧,只保留g(3)的调用帧。

函数尾递归优化

原理同上

暂存变量

当多次使用一个对象中的属性或方法返回的变量时,我们应该通过定义新的变量存储,而不是反复去作用域链上取值。

优化循环 

下面代码循环时会反复取imgs中的length属性,应通过定义新变量优化。

//var imgLength=img.length
//通过上面注释可优化
for(var i = 0; i <=imgs.length; i++) {
   //执行代码
}

尽量使用原生方法

原生方法是用诸如c/c++之类的编译型语言写出来的,所以要比JavaScript的自己定义的新方法要快很多很多。

使用switch替代if-else

如果有一系列复杂的if-else语句,可以转化成单个switch语句则可以得到更快的代码。还可以通过case语句按照最可能的到最不可能的顺序进行组织,来进行进一步优化switch语句。

减少语句数

简化申明

 var name = "Bill";
 var  age = 10;
 var  sex = "man";
 //简化为一个语句申明变量
 var name = "Bill",
     age = 10,
     sex = "man";

 合并语句

 var age = values[i];
 i++;
 //合并为一个语句
 var age = values[i++];

使用数组和对象字面量

 var values = new Array();
 values[0] = 123;
 values[1] = 456;
 values[2] = 789;
 var person = new Object();
 person.name = "Bill";
 person.age = 10;
//优化后
 var values = [123, 456, 789];
 var person = {
       name : "bill",
       age : 10,
 };

去除注释和空行

通常在webpack的打包文件会自动被去除,也可自行设置是否去除注释。

减少页面的重排(回流)和重绘

使用文档碎片减少DOM交互

例如下面代码,每执行一次for循环都会向DOM插入新的元素,一旦for循环次数很多,将严重影响代码性能,所以解决办法就是减少DOM交互,于是我们使用createDocumentFragment方法创建虚拟节点,把要插入DOM的元素先插入该虚拟节点,循环完之后再把虚拟节点插入DOM,虚拟节点是不会渲染出来的,只会渲染它的子节点

var list = document.getElementById("myList"),
       item,
       i;

 for (i = 0; i <= 10; i++) {
      item.document.createElement("li");
      list.appendChild(item);
      item.appendChild(document.createTextNode(" Item" + i));
 }
//优化后
var list = document.getElementById("myList");
       //构建虚拟节点
       fragment = document.createDocumentFragment(),
       item,
       i;

 for (i = 0; i < 10; i++) {
      item = document.createElement("li");
      fragment.appendChild(item);
      item.appendChild(document.createTextNode("Item" + i));
 }

 list.appendChild(fragment);

多次样式改变属性合并

浏览器会维护一个队列,将所有引起重排和重绘的操作都放在这个队列里,当操作达到一定的数量或者时间间隔时,浏览器会进行一个批处理。这样可以让多次的重排重绘,变成一次。

var el = document.getElementById("el");
el.style.color = "red";
el.style.height = "100px";
el.style.width = "20px";
//优化后
var el = document.getElementById("el");
el.style.cssText = 'color: red; height:100px; width:20px'

使用innerHTML

有两种在页面上创建DOM节点的方法:诸如createElement()和appendChild()之类的DOM方法,以及使用innerHTML。当把innerHTML设置为某个值时,后台会创建一个HTML解析器,然后使用内部的DOM调用来创建DOM结构,而非基于JavaScript的DOM调用,由于内部方式是编译好的而非解释执行的,所以执行快的多。

缓存多次使用的特殊属性

多次使用例如offsetTop,scrollTop,clientTop等属性(这些属性都是要实时返回给用户的几何属性或者布局属性)时,进行申明变量缓存。

避免使用document.write

document.write会导致页面重排。

减少drawImage

canvas的drawImage方法也会导致页面重排。

其它非代码方面

DOM的重排(回流)和重绘(页面渲染过程、重排、回流和重绘概念及其触发操作、浏览器对重排和重绘的优化策略、其它优化方法(基于HTML、CSS方面优化、基于JavaScript方面优化))_AIWWY的博客-CSDN博客

事件优化

使用事件委托

把事件绑定在祖先节点,由于有事件冒泡,当事件触发时根据event对象的target属性可以知道具体事件是在那个子元素发生的。从而执行不同的行为。这样就不必每个子节点都绑定事件。

TOUCH事件优化

使用touchstart、touchend代替click,因响应速度快。但应注意Touch响应过快,易引发误操作。

高频事件优化

Touchmove、Scroll 事件可导致多次渲染

a) 使用requestAnimationFrame监听帧变化,使得在正确的时间进行渲染

b) 增加响应变化的时间间隔,减少重绘次数

其它

多条字符串拼接

多条字符串拼接,存放数后使用array.join()方法进行拼接,效率会比+=高。 

 避免空的图片src

空的图片src仍然会使浏览器发送请求到服务器,这样完全是浪费时间,而且浪费服务器的资源。尤其是你的网站每天被很多人访问的时候,这种空请求造成的伤害不容忽略。例如下面代码:

var img = new Image();
img.src = "";

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值