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

前言

闭包(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() // 生成闭包

闭包生成条件

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

总结

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

相关推荐
jktantan4 小时前
Vue keep-alive 切标签后滚动位置回顶?因为 onDeactivated 里读到的 scrollTop 是 0
前端·javascript·vue.js
总要学点什么4 小时前
第89篇:三维特效-螺旋圆效果——让螺旋臂卷起一圈圈外扩的涟漪
开发语言·javascript·ecmascript·webgl·cesium·空间分析·1024程序员节
2601_962885724 小时前
quotes 字段全解:涨跌幅、振幅、换手率的口径与单位
java·前端·spring
excel5 小时前
encodeURI 和 encodeURIComponent 有什么区别?
前端
前端精髓5 小时前
调用openrouter的免费API模型
java·前端·javascript
赛博守夜人5 小时前
AI安全攻防与治理之十四:AI 安全测试不能脱离传统安全,Web、API、移动端与模型攻击面的组合拳
前端·人工智能·安全
开开心心_Every5 小时前
快速隐藏程序工具自定义快捷键一键切换
java·开发语言·前端·spring·智能手机·word·intellij-idea
networknomad6 小时前
OpenReplay:自己搭的会话回放工具,给前端排错用的
前端·其他
缓慢更新7 小时前
AI 辅助生成单测:从接口定义到用例的流水线
java·服务器·前端·网络·数据库·人工智能
陈随易7 小时前
AI 运维服务器,安全又可靠的方法
前端·后端·程序员