如同其他编程语言,代码的写法和算法会影响JavaScript的运行时间,与其他语言的不同的是,JavaScript的可用资源有限,因此优化技术更为重要,这个学习笔记主要是从JavaScript的循环、条件语句、递归这三个方面的一些奇淫技巧来优化JavaScript的性能。
循环
for、while和do-while循环性能特性相似,for-in相比前三者慢
- 由于每次迭代操作会同时搜索实例或者原型属性,for-in循环的每次迭代都会产生更多的开销,因此比其他循环类型要慢,对比相同迭代次数的循环,for-in循环最终只有其他类型速度的1/7,因此,除非你明确需要迭代一个属性数量未知的对象,否则应该避免使用
- for-in循环。还有不要使用for-in来循环数组成员。 改善循环性能的最佳方式是减少每次迭代的运算量和减少循环迭代次数。
- forEach(),此方法是ECMA-262引入的一新的原生数组方法,此方法遍历一个数组的多有成员,并且在每个成员上面执行一个函数。
//基于函数的迭代方法
item.forEach(function(value,index,array){
process(value);
})
//方便!!但是慢,这个要考虑。
条件语句
通常来说,switch总是比if-else快,并不总是最佳解决方案
- 使用if-else还是switch,基于测试条件的数量来判断:条件数量越大,越倾向于使用switch(考虑到代码的易读性),反之if-else更易读。
- 事实证明,大多数情况下switch比if-else运行得要快,但只有当条件数量很大时候才快得明显。
优化if-else,确保最可能出现的放在首位
- 优化的目标是使最小化到达正确分支所需判断的条件数量,最简单的就是确保最可能出现的放首位。
- 还有一种减少判断次数的方法是把if-else组成一系列的嵌套的if-else语句。
- 当你使用查找表时候,必须完全抛弃条件判断语句,这个过程变成数组项查询或者对象成员查询。
- 优点:不用写任何条件判断语句,既是候选值增加时,也几乎不会产生额外的性能开销。
在判断调节较多的时候,使用查找表比if-else和swich更快
//将返回值存入数组
var results=[result0,result1,result2,result3,result4,result5,
result6,result7,result8,result09]
//返回当前结果
return results[value];
递归
- 浏览器的调用栈大小限制了递归算法在JavaScript中的应用,栈溢出错误会导致其他代码中断运行。
- 如果你遇到栈溢出错误,可以将方法改为迭代算法,或使用Memoization来避免重复计算。
合并字符串
拼接字符串是编程中最常见的操作了,我们先来总结一下 JavaScript 中连接字符串的方法:
- +
- +=
- Array.prototype.join()
- String.prototype.concat()
- ES6 新增的模板字符串
当拼接少量较短字符串,以上这些方法速度都差不多。但随着需要连接的字符串的长度和数量的增加,一些方法开始展现出优势。
待连接字符串是变量
如果要拼接的字符串中有以变量形式存在的字符串,优先使用 ES6 中的模板字符串。
将变量名包裹在 ${} 中,然后使用反引号(` )包裹变量和普通字符串:
`${username}学会了开车.`
+ 和 +=
我们首先必需弄明白一点,在 JavaScript 中字符串一经初始化值便是不可改变的。
下面是一个拼接字符串的常见操作:
str += 'now' + 'old';
上面代码在运行时,会历经以下四个步骤:
- 在内存中创建一个临时字符串
- 拼接后的字符串 nowold被赋值给该临时字符串
- 临时字符串与 str 当前的值进行连接
- 将上一步的拼接结构赋值给 str
为了避免产生临时字符串造成额外的性能开销,我们可以这样做:
str += 'now';
str += 'old';
如果使用下面这种方式,我们能获得更显著的性能提升:
str = str + 'now' + 'old';
// 等价于 str = ((str + 'now') + 'old');
注意,上面代码中如果赋值号右侧表达式中的 str 不是处在最左侧,那么将得不到优化效果,这与浏览器合并字符串时分配内存的方法有关。大多数浏览器都会尝试为表达式左侧的字符串分配更多的内存,然后简单地将第二个字符串拷贝至它的末尾。如果在一个循环中,基础字符串位于最左侧的位置,就可以避免重复拷贝一个逐渐变大的基础字符串。
合并数组项
Array.prototype.join() 方法将数组中地所有元素合并成一个字符串,它接收一个参数作为每项之间的分隔符。如果传入参数为空字符,那么我们就可以使该方法将所有数组项连接为一个字符串。
然而,现实情况是,在大多数浏览器中,数组项合并比其他字符串连接方法更慢。
String.prototype.concat()
包装类型 String 的原生方法 String.prototype.concat() 能够接受任意数量的参数,并将每一个参数附加到所调用的字符串上,这是最灵活的字符串合并方法。
遗憾的是,在多数情况下,使用 cancat() 方法比使用简单的 + 和 += 稍慢。
总结:如果要合并的字符串中存在变量,那么使用模板字符串;否则,仅使用简单的 + 操作符合并字符串,并将基础字符串置于表达式最左侧。
评论 (0)