常规优化

最后更新于:2022-04-01 04:51:58

## 常规优化 > * 传递方法取代方法字符串 > > > > 一些方法例如`setTimeout()`、`setInterval()`,接受`字符串`或者`方法实例`作为参数。直接传递方法对象作为参数来避免对字符串的二次解析。 > > > * 传递方法 > > > > ~~~ > setTimeout(test, 1); > ~~~ > > > * 传递方法字符串 > > > > ~~~ > setTimeout('test()', 1); > ~~~ > > > * 使用原始操作代替方法调用 > > > > 方法调用一般封装了原始操作,在性能要求高的逻辑中,可以使用原始操作代替方法调用来提高性能。 > > > * 原始操作 > > > > ~~~ > var min = a<b?a:b; > ~~~ > > > * 方法实例 > > > > ~~~ > var min = Math.min(a, b); > ~~~ > > > * 定时器 > > > > 如果针对的是不断运行的代码,不应该使用`setTimeout`,而应该是用`setInterval`。`setTimeout`每次要重新设置一个定时器。 > > > * 避免双重解释 > > > > 当`JAVASCRIPT`代码想解析`JAVASCRIPT`代码时就会存在双重解释惩罚,双重解释一般在使用`eval`函数、`new Function`构造函数和`setTimeout`传一个字符串时等情况下会遇到,如。 > > > > ~~~ > eval("alert('hello world');"); > var sayHi = new Function("alert('hello world');"); > setTimeout("alert('hello world');", 100); > ~~~ > > > > 上述`alert('hello world');`语句包含在字符串中,即在JS代码运行的同时必须新启运一个解析器来解析新的代码,而实例化一个新的解析器有很大的性能损耗。 我们看看下面的例子: > > > > ~~~ > var sum, num1 = 1, num2 = 2; > /**效率低**/ > for(var i = 0; i < 10000; i++){ > var func = new Function("sum+=num1;num1+=num2;num2++;"); > func(); > //eval("sum+=num1;num1+=num2;num2++;"); > } > /**效率高**/ > for(var i = 0; i < 10000; i++){ > sum+=num1; > num1+=num2; > num2++; > } > ~~~ > > > > 第一种情况我们是使用了new Function来进行双重解释,而第二种是避免了双重解释。 > > > * 原生方法更快 > > > * 只要有可能,使用原生方法而不是自已用JS重写。原生方法是用诸如C/C++之类的编译型语言写出来的,要比JS的快多了。 > * 最小化语句数 > > > > JS代码中的语句数量也会影响所执行的操作的速度,完成多个操作的单个语句要比完成单个操作的多个语句块快。故要找出可以组合在一起的语句,以减来整体的执行时间。这里列举几种模式 > > > * 多个变量声明 > > > > ~~~ > /**不提倡**/ > var i = 1; > var j = "hello"; > var arr = [1,2,3]; > var now = new Date(); > /**提倡**/ > var i = 1, > j = "hello", > arr = [1,2,3], > now = new Date(); > ~~~ > > > * 插入迭代值 > > > > ~~~ > /**不提倡**/ > var name = values[i]; > i++; > /**提倡**/ > var name = values[i++]; > ~~~ > > > * 使用数组和对象字面量,避免使用构造函数Array(),Object() > > > > ~~~ > /**不提倡**/ > var a = new Array(); > a[0] = 1; > a[1] = "hello"; > a[2] = 45; > var o = new Obejct(); > o.name = "bill"; > o.age = 13; > /**提倡**/ > var a = [1, "hello", 45]; > var o = { > name : "bill", > age : 13 > }; > ~~~ > > > * 避免使用属性访问方法 > > > * JavaScript不需要属性访问方法,因为所有的属性都是外部可见的。 > * 添加属性访问方法只是增加了一层重定向 ,对于访问控制没有意义。 > > > > 使用属性访问方法示例 > > > > ~~~ > function Car() { > this .m_tireSize = 17; > this .m_maxSpeed = 250; > this .GetTireSize = Car_get_tireSize; > this .SetTireSize = Car_put_tireSize; > } > > function Car_get_tireSize() { > return this .m_tireSize; > } > > function Car_put_tireSize(value) { > this .m_tireSize = value; > } > var ooCar = new Car(); > var iTireSize = ooCar.GetTireSize(); > ooCar.SetTireSize(iTireSize + 1); > ~~~ > > > > 直接访问属性示例 > > > > ~~~ > function Car() { > this .m_tireSize = 17; > this .m_maxSpeed = 250; > } > var perfCar = new Car(); > var iTireSize = perfCar.m_tireSize; > perfCar.m_tireSize = iTireSize + 1; > ~~~ > > > * 减少使用元素位置操作 > > > * 一般浏览器都会使用增量reflow的方式将需要reflow的操作积累到一定程度然后再一起触发,但是如果脚本中要获取以下属性,那么积累的reflow将会马上执行,已得到准确的位置信息。 > > > > ~~~ > offsetLeft > offsetTop > offsetHeight > offsetWidth > scrollTop/Left/Width/Height > clientTop/Left/Width/Height > getComputedStyle() > ~~~
';