参考原文:javascript性能优化
Javascript的加载与执行
大家都知道,浏览器在解析DOM树的时候,当解析到script标签的时候,会阻塞其他的所有任务,直到该js文件下载、解析执行完成后,才会继续往下执行。因此,这个时候浏览器就会被阻塞在这里,如果将script标签放在head里的话,那么在该js文件加载执行前,用户只能看到空白的页面,这样的用户体验肯定是特别烂。
- 将所有的script标签都放到body最底部。
这样可以保证js文件是最后加载并执行的,可以先将页面展现给用户。但是,你首先得清楚,页面的首屏渲染是否依赖于你的部分js文件,如果是的话,则需要将这一部分js文件放到head上。
- defer
<script src="test.js" type="text/javascript" defer></script>
当浏览器解析到该标签时,尽管会下载对应的JavaScript文件,不过不会马上执行,而是等到DOM解析完之后才去执行。因此,就不会阻塞到浏览器。
javascript作用域链
对于一个函数而言,其第一个作用域就是它函数内部的变量。在函数执行过程中,每遇到一个变量,都会搜索函数的作用域链找到第一个匹配的变量,首先查找函数内部的变量,之后再沿着作用域链逐层寻找。因此,若我们要访问最外层的变量(全局变量),则相比直接访问内部的变量而言,会带来比较大的性能损耗。因此,我们可以将经常使用的全局变量引用储存在一个局部变量里。(访问的作用域链跨度越大,越消耗性能)
const a = 5;
function outter () {
const a = 2;
function inner () {
const b = 2;
console.log(b); // 2
console.log(a); // 2
}
inner();
}
原型链
javascript中,主要分为字面量、局部变量、数组元素和对象这四种。访问字面量和局部变量的速度最快,而访问数组元素和对象成员相对较慢。
而访问对象成员的时候,就和作用域链一样,是在原型链(prototype)上进行查找。因此,若查找的成员在原型链位置太深,则访问速度越慢。
因此,我们应该尽可能的减少对象成员的查找次数和嵌套深度。
// 进行两次对象成员查找
function hasEitherClass(element, className1, className2) {
return element.className === className1 || element.className === className2;
}
// 优化,如果该变量不会改变,则可以使用局部变量保存查找的内容
function hasEitherClass(element, className1, className2) {
const currentClassName = element.className;
return currentClassName === className1 || currentClassName === className2;
}
事件委托
事件委托就是将目标节点的事件移到父节点来处理,由于浏览器冒泡的特点,当目标节点触发了该事件的时候,父节点也会触发该事件。因此,由父节点来负责监听和处理该事件。
ul li 的例子
垃圾回收,减少内存
而垃圾回收器判断一个对象为活对象还是死对象,是按照是否有活对象或根对象含有对它的引用来判定的。如果有根对象或者活对象引用了这个对象,它将被判定为活对象。所以我们需要通过手动消除这些引用来让垃圾回收器对回收这些对象。
一种方式是通过将值设为null来消除引用。通过将变量或对象的属性设为null
,可以消除引用,使原本引用的对象成为一个“孤岛”,然后在垃圾回收的时候对其进行回收。
网友评论