我们知道,前端开发的最佳实践意义包括性能优化,
前端的性能优化就包括尽可能的减少DOM操作
1.性能
1.1注意作用域
const 代替 不可变变量
避免 with 语句
O(1) 常数 不管有多少值,执行的时间都是恒定的。一般表示简单值和存储在变量中的值
O(log n) 对数 总的执行时间和值的数量相关,但是要完成算法并不一定要获取每个值。例如:二分查找
O(n) 线性 总执行时间和值的数量直接相关。例如:遍历某个数组中的所有元素
O(n 2 ) 平方 总执行时间和值的数量有关,每个值至少要获取n次。例如:插入排序
一旦多次用到对象属性,应该将其存储在局部变量中。第一次访问该值会是 O(n),然而后续的访问
都会是 O(1),就会节省很多。例如,之前的代码可以如下重写:
var url = window.location.href;
var query = url.substring(url.indexOf("?"));
避免双重解释
当 JavaScript 代码想解析 JavaScript 的时候就会存在双重解释惩罚。当使用 eval() 函数或者是
Function 构造函数以及使用 setTimeout() 传一个字符串参数时都会发生这种情况。下面有一些例子:
//某些代码求值——避免!!
eval("alert('Hello world!')");
//创建新函数——避免!!
var sayHi = new Function("alert('Hello world!')");
//设置超时——避免!!
setTimeout("alert('Hello world!')", 500);
在以上这些例子中,都要解析包含了 JavaScript 代码的字符串。这个操作是不能在初始的解析过程
中完成的,因为代码是包含在字符串中的,也就是说在 JavaScript 代码运行的同时必须新启动一个解
析器来解析新的代码。实例化一个新的解析器有不容忽视的开销,所以这种代码要比直接解析慢得多。
对于这几个例子都有另外的办法。只有极少的情况下 eval() 是绝对必须的,所以尽可能避免使用。
在这个例子中,代码其实可以直接内嵌在原代码中
2 最小化现场更新
符,放置新创建的项目。然后使用 appendChild() 将所有项目添加到列表中。记住,当给 appendChild()
传入文档片段时,只有片段中的子节点被添加到目标,片段本身不会被添加的。
一旦需要更新 DOM,请考虑使用文档片段来构建 DOM 结构,然后再将其添加到现存的文档中。
image,
i, len;
for (i=0, len=images.length; i < len; i++){
image = images[i];
//处理
}
这段代码添加了 image 变量,保存了当前的图像。这之后,在循环内就没有理由再访问 images 的
HTMLCollection 了 。
编写 JavaScript 的时候,一定要知道何时返回 HTMLCollection 对象,这样你就可以最小化对他们
的访问。发生以下情况时会返回 HTMLCollection 对象:
进行了对 getElementsByTagName() 的调用;
获取了元素的 childNodes 属性;
获取了元素的 attributes 属性;
访问了特殊的集合,如 document.forms 、 document.images 等