JS - 函数进阶内容

137 阅读2分钟

递归

递归是一种编程模式,可以将一个任务拆分为多个相同类型但更简单的任务,或者将一个任务简化为一个简单的行为加上该任务的一个更简单的变体。

最大递归深度受限于 JS 引擎。对我们来说,引擎在最大迭代深度为 10000 及以下时是可靠的。

执行上下文和堆栈

一个函数调用有且仅有一个与其相关联的执行上下文。

执行上下文是一个内部数据结构,它包含有关函数执行时的环境的信息:

  • 当前控制流所在的位置
  • 当前的变量
  • this 的值
  • 其他内部细节

当一个函数进行嵌套调用时:

  • 当前函数暂停
  • 与它关联的执行上下文被推入一个称为执行上下文堆栈的特殊内部数据结构中
  • 执行嵌套调用
  • 当嵌套调用完成时,从堆栈中弹出执行上下文,并恢复执行

Rest 参数

Rest 语法 ...rest 可以收集剩余参数放入数组。

而过去的 JS 通过 arguments 获取函数所有参数,但它是一个类数组对象,不能使用数组的方法。

function sumAll(...args) {
  let sum = 0
  for (let arg of args) sum += arg
  return sum
}

function showArgs() {
  console.log(arguments.length)
  for (let arg of arguments) console.log(arg)
}

Spread 语法

Spread 语法 ...arr 用于将可迭代对象展开。

let arr1 = [3, 5, 1]
let arr2 = [4, 6, 8]

Math.max(...arr1)
Math.max(...arr1, ...arr2)
Math.max(1, ...arr1, 2, ...arr2, 25)

let merged = [...arr1, ...arr2]

// 进行浅拷贝
let arrCopy = [...arr]
let objCopy = { ...obj }

词法环境

JS 中,每个运行的函数,代码块以及整个脚本文件,都有一个被称为词法环境(Lexical Environment)的内部隐藏的关联对象。

词法环境对象由两部分组成:

  1. 环境记录(Environment Record),一个存储所有局部变量作为其属性(还包括一些其他信息,例如 this 的值)的对象
  2. 对外部词法环境的引用,与外部代码相关联

一个变量代表环境记录中的一个属性,获取或修改变量代表获取或修改词法环境中的一个属性。

举个例子,这段没有函数的简单代码中只有一个词法环境,也就是整个脚本文件关联的全局词法环境:

image.png

随着代码运行,词法环境发生了变化:

image.png

词法环境会预先填充所有声明的变量