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

前言

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

闭包生成条件

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

总结

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

相关推荐
天天向上10246 分钟前
Vue 配置打包后可编辑的变量
前端·javascript·vue.js
芬兰y22 分钟前
VUE 带有搜索功能的穿梭框(简单demo)
前端·javascript·vue.js
好果不榨汁29 分钟前
qiankun 路由选择不同模式如何书写不同的配置
前端·vue.js
小蜜蜂dry29 分钟前
Fetch 笔记
前端·javascript
拾光拾趣录30 分钟前
列表分页中的快速翻页竞态问题
前端·javascript
小old弟31 分钟前
vue3,你看setup设计详解,也是个人才
前端
Lefan35 分钟前
一文了解什么是Dart
前端·flutter·dart
Patrick_Wilson40 分钟前
青苔漫染待客迟
前端·设计模式·架构
vvilkim42 分钟前
Nuxt.js 全面测试指南:从单元测试到E2E测试
开发语言·javascript·ecmascript
写不出来就跑路1 小时前
基于 Vue 3 的智能聊天界面实现:从 UI 到流式响应全解析
前端·vue.js·ui