书中有悟:一文讲清楚闭包和作用域之间的关系!

前言

闭包(closure)对于大家来说应该已经不陌生了,但是当有人问你时,你真的能讲清楚什么是闭包吗?今天这篇文章通过结合红宝书及黄宝书中对闭包的定义,来讲一下闭包和词法作用域之间的关系及什么是真正意义上的闭包。

关键词: 闭包、词法作用域。

如何查看闭包

首先我们创建一个html文件在浏览器打开,运行一段生成闭包的js代码。

js 复制代码
function fn() {
  var name = 'lgh'
  function fn2() {
    console.log(name)
  }
  fn2()
}
fn()

这里以谷歌浏览器为例:F12打开控制台 > 点击Source标签 > Scope > closure。具体操作可看下图示例:

上图在第14行运行时可生成闭包,所以在此处打了个断点,运行到此处就会停下来,在右侧的Scope下的closure属性出可看到在执行fn2时,生成了一个涵盖fn函数作用域的闭包,闭包下包含对外层函数变量name的引用。

闭包的定义

下面是在这两本书中关于闭包的定义。

1.javascript高级程序设计: 闭包指的是那些引用了另一个函数作用域中变量的函数,通常是在嵌套中实现的。

2.你不知道的JavaScript: 当函数可以记住并访问所在词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行。

从第二个定义来看 ,其实是不认同上面的例子是闭包的。更准确来说fn2函数对a的引用方法是词法作用域的查找规则,简单来说就是fn2函数是在fn函数的词法作用域中定义并执行了,并不是真正意义上的闭包,而只是闭包的一部分!而真正意义上的闭包应该在自己定义的词法作用域外执行。即以下这段代码才是真正的闭包:

js 复制代码
function fn() {
  var name = 'lgh'
  function fn2() {
    console.log(name)
  }
  return fn2;
}
const fn3 = fn()
fn3() // 输出:lgh

fn函数通过return返回fn2,并在fn函数的词法作用域外执行,并且访问到了fn函数内的变量name,这才应该是闭包的效果;而不是引用单纯的词法作用域查找就能访问的变量。

这里也有一个容易理解的误区是只有函数内部返回一个引用了其内部作用域变量的函数才算是闭包。

参考以下例子其实也是闭包:

js 复制代码
// 函数传递
function fn2(cb) {
  cb() // 输出lgh。这也是闭包,在fn的词法作用域外执行了fn3
 }

 function fn() {
  var name = 'lgh'
  function fn3() {
    console.log(name)
  }
  fn2(fn3)
 }

 fn()
js 复制代码
// 变量赋值
 var fn

 function fn2() {
  var name = 'lgh'
  function fn3() {
    console.log(name)
  }
  fn = fn3  // 内部函数赋值给外部变量
 }

 function fn4() {
  fn() // 闭包
 }

 fn2() // 执行赋值操作
 fn4() // 生成闭包

闭包生成条件

闭包是在运行时生成的。闭包 是指一个函数对象,它不仅包含了函数的代码,还记录了函数创建时的环境信息,包括函数内部的变量、参数等。这些环境信息使得闭包可以在函数定义的作用域之外被调用,并且可以访问到其定义时的变量状态。

总结

闭包可以是那些引用了另一个函数作用域中变量的函数。但真正意义上的闭包是在定义它的词法作用域外执行才能发挥它的真正的效果,也是严格意义上的闭包!

相关推荐
骑着蜗牛撵大象3275 小时前
豆包 Seed 驱动的记账智能体:从拍票抽取到月报生成的全链路落地记录
java·前端·javascript·结构化输出·豆包seed·多模态识别·记账系统
溪语流沙5 小时前
【Web全栈进阶】前端世界观:现代工具链与框架为什么存在
前端·javascript·vue.js
kyriewen6 小时前
我逐个测了 JSON.stringify 的 7 个坑:第 1 个就在丢数据
前端·javascript·程序员
积流成海6 小时前
用代码实现哈希计算器:Web Crypto API 实战
前端·算法·哈希算法·哈希函数·盘子工具站
data analyse 4566 小时前
服务端访问日志聚合 PV 与 UV 怎么实现?日志采集与口径设计
大数据·前端·数据分析
song5016 小时前
React Native for OpenHarmony 实战:三方库 react-native-ratings 的鸿蒙化适配指南
javascript·react native·react.js·分类·harmonyos
JavaGuide6 小时前
DeepSeek Harness 重磅更新,Codex、Claude Code 子智能体进官方插件列表了,还有 Git 工作树和思考翻译!
前端·后端
小羊没烦恼!7 小时前
OS X 上使用.NET开发应用程序
开发语言·前端·数据库·人工智能·c#·策略模式
朱包林7 小时前
iTerm2终端配置指南
linux·javascript·python·云原生·容器·kubernetes·云计算
谢亮_vipxieliang7 小时前
JavaScript this 指向完全指南:调用位置决定一切
开发语言·javascript·ecmascript