这是我参与8月更文挑战的第9天,活动详情查看: 8月更文挑战编程
业务代码开发多了,其实就是在写 if-else数组
与条件判断相比,循环语句对程序执行性能的影响更大。一个循环语句的循环执行次数直接影响程序的时间复杂度,若是代码中还存在缺陷致使循环不能及时中止,从而形成死循环,那么给用户带来的使用体验将会是很是糟糕的。本文记录,怎样编写循环语句能对性能产生有益的影响。markdown
JavaScript中循环语句的常见写法有三种,第一种是标准的for循环,这与大部分编程语言相似,包括初始化、循环结束条件、迭代语句及循环体四部分,代码示例以下:数据结构
// 标准for循环
for(let i = 0; i < length; i ++){
// 循环体
}
复制代码
第二种和第三种分别是while循环和do-while循环,两者惟一的差异就是do-while循环会先执行一遍循环体,再去判断循环结束条件,代码示例以下:app
// while循环
let i = 0
while(i < length){
// 循环体
i ++
}
// do-while 循环
do {
// 循环体
i ++
} while (i < length)
复制代码
一般在使用这三种循环语句时,基本场景都是对数组元素进行遍历。从索引的第一个元素开始直到数组的最后一个元素结束,每次在执行循环判断时,都须要将当前的数组索引与数组长度进行比较。因为该比较操做执行的过程当中数组长度通常不会改变,且存取局部变量要比查找属性值更省时,因此提早将要遍历的数组长度声明为局部变量,而后将该局部变量进行循环结束的条件判断,效率会更高一些。下面以for循环为例:编程语言
// 较差的循环结束判断
const array = [1,2,3,4,5]
for(let i = 0; i < array.length; i ++){
// 省略循环体过程
}
// 较好的循环结束判断
const len = array.length
for(let i = 0; i < len; i ++){
// 省略循环体过程
}
复制代码
这在对包含较大规模DOM节点数的遍历过程当中,效果会更加明显。此外还有一种更简单的提高循环语句性能的方式:将循环变量递减到0,而非递增到数组总长度ide
// 更好的循环结束判断
for(let i = arr.length - 1; i > 0; i --){
// 省略循环体过程
}
复制代码
由于循环结束的判断是和常量0进行比较的,不存在对数组长度属性值的查找或局部变量的读取,其比较的运算速度会更快。因为三种循环语句的执行性能基本相似,因此仅针对结束条件的判断进行优化。函数
for-in可用来遍历JavaScript对象的可枚举属性,一般用法以下:post
// 遍历object对象的全部属性
for(let prop in object){
// 确保不会遍历到object原型链上的其余对象
if(object.hasOwnProperty(prop)){
// 相关属性的处理过程
}
}
复制代码
能够看出for−in循环可以遍历对象的属性集,特别适合处理诸如JSON对象这样的未知属性集,但对一般的循环使用场景来讲,因为它遍历属性的顺序不肯定,循环的结束条件也没法改变,而且由于须要从目标对象中解析出每一个可枚举的属性,即要检查对象的原型和整个原型链,因此其循环速度也会比其余循环方式要慢许多,若是循环性能有要求则尽可能不要使用for−in循环。性能
另外对于数组的循环,JavaScrpt原生提供了一种forEach函数选代的方法,此方法会遍历数组上的全部元素,并对每一个元素执行一个方法,所运行的方法做为forEach函数的入参,代码以下:
//对数组进行函数选代
myArray.forEach((value, index, arr) => {
// 可处理数组中的每一个元素
})
复制代码
这种方法使用起来的确会让数组元素的迭代看起来更加直观,但在一般状况下与三种基本的循环方法相比,其性能方面仅能达到后者的1/8,若是数组长度较大或对运行速度有比较严格的要求,则函数迭代的方式不建议使用。
同时还有一种for语句的变形,就是ES6加入的for−of循环,咱们可使用它来代替for-in和forEach循环,它不只在性能方面比这两者更好,而且还支持对任何可选迭代的数据结构进行遍历,好比数组、字符串、映射和集合,但与三种常规循环语句相比其性能仍是稍逊色一些的。