专业编程教程与实战项目分享平台

网站首页 > 技术文章 正文

两个小案例让你深入理解 Javascript 闭包和作用域

ins518 2024-10-04 23:59:20 技术文章 15 ℃ 0 评论

作为 js 基础知识的 三座大山之一的闭包和作用域,一直是前端笔面试中常考的知识点。

基于作用域和闭包的笔试题是层出不穷,今天让我们抽丝剥茧,透过现象看本质,从两个小案例去加深闭包和作用域的理解。同时也可以窥探作用域和闭包在 js 运行时中如何工作的。

前言

看案例之前,我们先回顾一下作用域和闭包的基础概念。

作用域: 简单来说就是决定了变量、函数和对象的可访问性。它定义了代码块中声明的标识符(如变量和函数)在何处可用。作用域一般分为:全局作用域、函数作用域、块级作用域、词法作用域和模块作用域

闭包: 就是一个函数以及其捆绑的周边环境状态(lexical environment,词法环境)的引用的组合。简单来说,就是可以从内部函数访问外部函数的作用域的一种组合。

案例1:嵌套函数场景

我们来看有闭包场景的作用域链的访问过程。

在控制台上可以直接运行出结果就是 10

我们可以分析一下上面的的执行过程。

脚本准备阶段

在脚本执行前,js 解释器会收集函数的声明进行变量提升。所以此时 outsideFn 函数会被初始化在内存中。而 innerFn 函数由于是局部函数,所以并不会有变量提升。

执行阶段

  1. outsideFn 函数执行时会被推上调用栈中
  1. 在 outsideFn 函数内中
  • innerVar 会被赋值为 10
  • innerFn 函数被调用并推送到调用栈中
  1. 在 innerFn 函数内部
  • console.log('innerVar', innerVar)执行的时候会根据作用域查找 innerVar 这个变量。
  • 通过debug我们可以发现在函数作用域和全局作用域之间还存在一个闭包作用域
  • 这个闭包就是 outsideFn 函数在创建的时候就会创建(从上面的图中可以看出闭包的标记,Closure (outsideFn) 看出这个闭包是 outsideFn 函数创建的),这是和函数声明的词法作用域有关,和函数调用位置无关。

作用域的访问方向按上图的箭头进行

案例2:独立函数场景

我们来看这个案例,我们来梳理一下作用域的访问过程。

在控制台我们可以看到输出的结果:

脚本准备阶段

同理,在执行前, foo 函数和 bar 函数会通过变量提升到脚本顶部并完成初始化。

执行阶段

  1. foo 会被调用并推送到调用栈中
  1. 在 foo 函数中
  • x 变量 会从 undefined 变成 10
  • bar 函数调用,并推送到 调用栈中。
  1. 在 bar 函数中
  • console.log(x); 调用时,访问 x 变量,此时通过作用域链在 bar 函数作用域和全局作用域中找不到 x 变量。
  • 所以最终就会报错 ReferenceError: x is not defined

小结

通过上述案例,我们可以总结作用域和闭包有以下特性:

  • 作用域查找是从当前作用域进行向上查找直到全局作用域
  • 作用域就是定义了变量、函数和对象的可访问范围
  • 闭包在函数创建的时候就被同时创建了
  • 闭包是一个函数和其周围的词法环境存在关联的一个组合。
  • 和词法环境有关联才有闭包产生
  • 和词法环境没有关联,就不会有闭包产生

如果对你有帮助的话,欢迎点赞、关注?、转发

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表