从递归和循环的执行原理来看性能差别

202 阅读1分钟

递归的执行机制

    function recursiveTest() {
      let arr = [1, 2, 3]
      const fn = function (i) {
        arr[i] *= 10
        if(i === arr.length - 1){
          return
        }
        i++
        fn(i)
      }
      fn(0)
    }

当调用fn时会在内存中进行压栈,形成一个栈帧,内部调用fn,又产生新的栈帧。

如上图,递归是通过压入堆栈帧来记录执行步骤,fn(0)执行到fn(1)时,等待着fn(1)的执行完毕及其返回结果,fn(1)等待着fn(2)的执行完毕及其返回结果。 每一次递归的执行都要访问内存地址进行压栈和出栈,压入的数据包括变量和返回值地址。

循环的执行机制

    function forTest(){
      let arr = [1, 2, 3]
      let count = arr.length
      for(let i = 0; i < count; i++){
          arr[i] *= 10
      }
    }

如上图,循环的执行原理是通过改变内部变量和指令跳转实现的,且CPU改变局部变量是刷新寄存器,进一步减少了内存的访问。因此循环并不需要开辟新的内存空间,这也是为什么递归会有栈溢出而循环不会的原因。