现在AI 写的代码水平如何

698 阅读7分钟

AI 模型在 2022 年刚问世的时候很多人对此抱有疑问,事实上在开发人员的使用过程中发现,还难堪大用,借助 AI 编程,结果给出的代码自带 bug,我自己写的 bug 还没有修完呢,怎么可能有时间来帮 AI 修 bug?要是你对它给出的答案不满意,多问几遍,甚至它自己都连连抱歉,自顾自的不断给出不一样的答案😂

那时隔 2 年,现在的 AI 模型现在表现的怎么样了,它是否真的能提高我们的开发效率?

下面来看个例子,一探究竟!

数字时钟

数字时钟想必很多人都做过。

不就是简单的显示日期和时间吗?setInterval 一把梭哈!

<template>
  <span class="digital-clock">{{ currentDate }}</span>
</template>

<script>
import dayjs from 'dayjs'

export default {
  name: 'Clock',
  data() {
    return {
      dayType: [
        '星期日',
        '星期一',
        '星期二',
        '星期三',
        '星期四',
        '星期五',
        '星期六'
      ],
      currentDate: '',
    }
  },
  methods: {
    getTime() {
      this.currentDate = dayjs().format('YYYY-MM-DD HH:mm:ss') + ' ' + this.dayType[(new Date()).getDay()]
    },
  },
  mounted() {
    setInterval(() => {
      this.getTime()
    }, 1000)
  },
}
</script>

<style>
.digital-clock {
  display: flex;
  align-items: center;
  color: #83a9e5;
  font-size: 14px;
  vertical-align: middle;
}
</style>

image

效果:

等等先别着急,来看看 AI 写的。

<template>
  <span class="digital-clock">
    <span class="date">{{ date }}</span>
    <span class="digit">{{ hours }}</span>
    <span class="colon">:</span>
    <span class="digit">{{ minutes }}</span>
    <span class="colon">:</span>
    <span class="digit">{{ seconds }}</span>
  </span>
</template>

<script>
import dayjs from 'dayjs'

export default {
  name'Clock',
  data() {
    return {
      date'',
      hours'',
      minutes'',
      seconds'',
      currentTime'',
      prevTime'',
      myReq0,
      dayType: [
        '星期日',
        '星期一',
        '星期二',
        '星期三',
        '星期四',
        '星期五',
        '星期六'
      ],
    }
  },
  methods: {
    getDate () {
      this.date = dayjs().format('yyyy-MM-dd') + ' ' + this.dayType[(new Date()).getDay()]
    },
    updateTime() {
      const date = new Date()
      const h = this.padZero(date.getHours())
      const m = this.padZero(date.getMinutes())
      const s = this.padZero(date.getSeconds())

      this.hours = h
      this.minutes = m
      this.seconds = s
      this.currentTime = `${h}:${m}:${s}`
    },
    padZero(value) {
      return value < 10 ? `0${value}` : value
    },
    updateClock() {
      const currentTime = performance.now()
      const deltaTime = currentTime - this.prevTime

      if (deltaTime >= 1000) {
        this.updateTime()
        this.prevTime = currentTime
      }

      this.myReq = requestAnimationFrame(this.updateClock)
    }
  },
  mounted() {
    this.getDate()
    this.prevTime = performance.now()
    this.updateClock()
  },
  beforeDestroy() {
    cancelAnimationFrame(this.myReq)
  }
}
</script>

<style scoped lang="scss">
.digital-clock {
  display: flex;
  align-items: center;
  color: #83A9E5;
  font-size: 14px;
  vertical-align: middle;
}

.digital-clock .date {
  margin-right: 4px;
}

.digital-clock .digit {
  display: inline-block;
  width: 1.2em;
}

.digital-clock .colon {
  display: inline-block;
  width: 0.4em;
}
</style>

写的蛮好的嘞😳

效果:

分析一下

好家伙,没有直接用 setInterval,而是用了performance.now()requestAnimationFrame 来替代,通过精确的时间计算来达到每秒更新一次,确保时间更新的准确性和性能最佳。

image

setInterval 的问题

为什么setInterval性能差呢?主要有以下几点:

  1. 时间精度不可靠

setInterval 定时器的执行间隔并不一定是准确的。例如,setInterval(fn, 1000) 表示每隔 1000 毫秒执行一次 fn,但由于 JavaScript 是单线程运行的,其他任务(如页面渲染、大量的 DOM 操作、事件处理)可能会阻塞主线程,导致定时器的执行时间被延迟,无法保持精确的间隔。这种不精确性在处理时间敏感的任务时表现得尤为明显。

  1. 主线程阻塞

setInterval 运行在主线程上,如果主线程被其他操作(如繁重的计算、DOM 操作)阻塞,定时器的回调函数可能会延迟执行。这种延迟会积累,最终导致定时器的执行与预期不同,甚至出现多个回调函数在阻塞解除后“扎堆”执行的情况,从而导致性能下降。

  1. 缺乏协调性

setInterval 不会检查先前的回调是否已完成。因此,如果一个定时任务比设定的间隔时间运行得更长,新的定时器回调函数会在旧的回调执行完之前被触发,可能导致内存泄漏或其他意外行为。

  1. 浏览器节流和后台模式影响

现代浏览器对 setInterval 有节流机制,尤其是在页面切换到后台时,定时器的精度可能大幅降低。比如,Chrome 浏览器会降低后台页面的 setInterval 执行频率以节省资源,这会进一步影响时间任务的准确性。

  1. 性能劣化与垃圾回收

定时器创建和销毁的频率高且不受控,可能会导致垃圾回收频繁运行,进一步降低性能。

requestAnimationFrame 和 performance 的优势

前面说了,这两个确保了时间更新的准确性和性能最佳,通过对比上次更新时间当前时间来确定是否需要更新显示的时间,从而实现每秒更新一次。

使用 performance.now() 可以获取高精度的时间戳,而不是依赖 JavaScript 的 Date 对象的低精度时间更新。

requestAnimationFrame 更加适合做高频率的任务调度,主要原因如下:

  1. 与浏览器刷新同步

requestAnimationFrame 会自动将回调函数的执行时间安排在下一次浏览器重绘之前,这意味着它的执行频率与屏幕的刷新率保持同步(通常为每秒 60 次),从而避免了不必要的额外渲染和计算。相比之下,setInterval 会尝试按照设定的时间间隔执行,但不会考虑屏幕刷新节奏,这可能导致丢帧和卡顿。

  1. 节省 CPU 资源

requestAnimationFrame 在后台标签页或非活动状态时会暂停执行回调函数,节省了 CPU 资源。而 setInterval 即使在后台标签页也会尝试执行,浪费了系统资源。requestAnimationFrame 的这一特性特别适用于需要节约电量或优化资源的场景。

  1. 防止页面卡顿

在高频率任务调度中,requestAnimationFrame 通过与浏览器的绘制流程协同工作,可以避免多个回调函数扎堆执行的情况。这种协调性降低了页面卡顿的风险,因为浏览器可以更好地控制和优化任务的执行时机。

  1. 精确控制动画帧率

requestAnimationFrame 让开发者能够精确地控制动画的帧率,使动画和其他高频任务更加流畅、自然。而 setInterval 的时间间隔是基于设置的毫秒数,且可能被其他任务阻塞,导致帧率不稳定或帧丢失。

  1. 减少不必要的绘制

当页面未处于可见状态或动画不可见时,requestAnimationFrame 会自动停止回调,这样可以有效减少不必要的绘制操作,避免浪费性能。

总的来说它优势在于与浏览器的渲染周期高度协调,使得它成为高频率、帧同步任务(如动画)的最佳选择。它不仅能确保任务以最佳的时间执行,还能优化性能、减少资源消耗,是现代前端动画和实时任务调度的理想工具。

最后还很贴心的做了防止数字变化时带来的文字抖动问题

完了,AI 要代替了我了

看完这个例子,你是不是有点慌张了,短短2年时间,AI已经可以代替程序员写代码了嘛,写的代码还更好了。

别急,事实上,AI 写的那段代码是经过多次修改,反复调教的结果,一开始它也是用 setInterval 来实现的数字时钟(hhhhhhh)。

经过不断的提示:要注意性能、要用 requestAnimationFrame、要考虑时间更新的精确度、试试 performance、时间变化会抖动,要解决等等

在编写过程中,反复调试,AI 才能得出我们满意的答案,这意味着是我们自己首先知道这些知识点,才去提示 AI 让它不断完善代码。

image

善用 AI

而实际上,善用 AI 确实能帮助我们提高开发效率,比如开发一些简单的组件、给 js 代码加上 ts 类型声明、数据格式转换等等事情,AI 做起来确实很快,省了很多时间。

还有目前比较完善的 AI 辅助编程,基本可以做到想你所想,提高开发效率。

AI 辅助编程工具:

  • 豆包MarsCode - 编程助手
  • github copilot
  • 通义千问
  • CodeGeeX

image.png

image

总的来说,我们是来做事情的,能又快又好的完成应该是我们的追求,快点做完不就能摸鱼了嘛;至于说 AI 取代程序员,可以换个角度看待,开发者的角色会慢慢的从单纯的编码者,转向问题解决者、设计者,让 AI 去做那些繁琐的编码任务,我们更关注架构设计、用户体验和创新点;对于新鲜事物,大可不必着急排斥,不如先试试~