自己卷自己?前端的低效代码性能优化

211 阅读2分钟

最近的某次代码评审中,某位同事对我的代码提出了一个优化点:for循环中不要去用this.xxx这样的语句,要用局部变量保存该属性,如:

for (let i = 0; i < this.tableData.length; i++) {
    const row = this.tableData[i];
    row.date = this.currentData;
}
// 应优化为
const tableData = this.tableData
const currentData = this.currentData
for (let i = 0; i < tableData.length; i++) {
    const row = tableData[i];
    row.date = currentData;
}

这个优化原理很简单,局部变量的访问速度比属性快,用局部变量去缓存属性自然能在循环中获得效率提升。

参与代码评审的领导听了觉得这种优化可以作为一种标准,每个for循环都这么处理,但是我提出异议,表示这样的优化不值得去做,因为只有数据量达到上万条可能才会有一点点效果,但领导觉得以后可能会碰上这种情况,还是坚持这个优化标准,我虽然还想反驳,但是一时也没想到太充分的理由。

所以会后我就开始思考,这种优化方式的优缺点,首先,实践出真知,我先写个简单的demo来看下这种优化提升的效率:

  <div id="app"></div>
  <script src="https://lib.baomitu.com/vue/2.6.14/vue.min.js"></script>
  <script>
    new Vue({
      el: '#app',
      data: {
        currentData: new Date(),
        tableData: []
      },
      created() {
        console.time('time') // 开始时间
        for (let i = 0; i < 1000; i++) {
          this.tableData.push({
            name: 'name',
            date: this.currentData
          })
        }
        console.timeEnd('time') // 结束时间
        // 优化后
        console.time('time2') // 开始时间
        const tableData = this.tableData
        const currentData = this.currentData
        for (let i = 0; i < 1000; i++) {
          tableData.push({
            name: 'name',
            date: currentData
          })
        }
        console.timeEnd('time2') // 结束时间
      },
      template: `<div>{{tableData.length}}</div>`
    })
  </script>

页面运行起来后,在控制台现实的代码执行时间分别为: image.png 也就是说,这种优化在上面的例子中做到了一千条数据提升了0.24ms的优化速度。再试试一万和十万条数据:

image.png 提升2.2ms。

image.png 提升55.1ms。
虽然这个例子比较简单,实际情况可能会更明显一点,但其实也是能看出,只有大量数据情况下,这种优化才有比较显著的效果,而在平常的业务开发中,这种大量数据是比较少见的。一般循环可能撑死了也就几百次,人根本感觉不出性能的提升,只有开发者孤芳自赏:哥的代码写的真是好!

这种优化的缺点是什么呢?就是代码的冗余!如果你的for循环里面调用了10个不同的属性,那么你将要多写10行代码,增加了工作量和降低了可读性,仅仅是为了优化一点微不足道的性能。
当然,如果一个for循环调用了多次相同的属性,我认为是可以用局部变量缓存起来的,因为这样做实际上即精简了代码,又提升了性能,一举两得。

以上的例子只是针对普通的前端业务开发,如果是在写框架或者工具,那么这种优化方式是没问题的,因为底层的工具总是需要尽可能地优化性能。

总结

前端代码优化是需要考虑成本和收益的,大家不要在某些文章里面看到一些优化方案,就生搬硬套把它用起来,而是要结合实际场景去考虑。
在我的工作经验中,前端业务开发最大的痛点不是性能,而是增强代码的可维护性、可读性和健壮性,应该把主要的精力放在这些方面,而不是在低效的优化中消耗自己有限的精力,陷入自我内卷的漩涡之中。