一篇文章教会你什么是闭包

菜园前端
• 阅读 353

原文链接:https://note.noxussj.top/?source=helloworld


什么是闭包?

闭包的概念并不复杂,但是它的定义比较绕(就像平时经常用到它,却又说不出来是什么)。可以在一个作用域中调用函数的内部函数并访问到该函数中的作用域的成员,这就是闭包。给一个建议,网上闭包的概念可以搜出来一大堆,但是你真的了解它吗?你有去调试看过它真的存在吗?一直处于理论状态,没有去真正实践过,这样的知识背下来了也没有太大意义,到面试的时候也表达不清楚。

闭包的原理

函数在执行的时候会放到一个执行栈中,当函数执行完毕之后会从执行栈移除,但是堆上的作用域成员因为被外部引用不能释放,因此内部函数依然可以访问外部函数的成员。

为了更好的理解,我列举以下两个场景,一个是存在闭包,一个是不存在闭包。并且通过浏览器调试工具去查看闭包。

基础案例

场景 1

function makeFn() {
    let msg = 'Hello function'

    console.log(msg)
}

makeFn()

执行过程如下:

  1. 定义 makeFn 函数
  2. 调用 makeFn 函数
  3. 定义 msg 变量
  4. 打印 msg 变量
  5. 销毁 msg 变量
  6. 执行完毕

调试结果

一篇文章教会你什么是闭包

从上图中可以看到,当我们准备打印 msg 变量的时候,它是从当前作用域读取出来的。

场景 2

function makeFn() {
    let msg = 'Hello function'

    return function inside() {
        console.log(msg)
    }
}

let fn = makeFn() // 执行 makeFn 函数,返回 inside 函数

fn() // 执行 inside 函数

执行过程如下:

  1. 定义 makeFn 函数
  2. 调用 makeFn 函数
  3. 定义 msg 变量
  4. 定义 inside 函数(虽然还没被调用,但是由于该函数访问了外部函数的变量,所以外部函数的执行上文对象不会被销毁,形成闭包)
  5. makeFn 函数执行完毕,并将 inside 函数返回给 fn
  6. 调用 fn 函数
  7. inside 函数访问 msg 变量(从闭包中获取 msg)
  8. 打印 msg 变量
  9. 执行完毕

调试结果

一篇文章教会你什么是闭包

从上图中可以看到,当我们准备打印 msg 变量的时候,它是从闭包里面读取出来的。

还有一点,闭包会造成内存泄露,这句话不完全对,何为内存泄露?例如上图的 msg 变量,是我想要访问的变量,它不叫内存泄露。内存泄露是指在闭包中存在一些我不想要的资源,或者是无意间生成出来的。

点赞
收藏
评论区
推荐文章
Souleigh ✨ Souleigh ✨
3年前
JS - 从执行上下文的角度来理解闭包
今天看到一篇关于闭包的文章,里面有这样一句话“就我而言对于闭包的理解仅止步于一些概念,看到相关代码知道这是个闭包,但闭包能解决哪些问题场景我了解的并不多”,这说的不就是我么,每每在面试中被问及什么是闭包,大部分情况下得到的答复是(至少我以前是)A函数嵌套B函数,B函数使用了A函数的内部变量,且A函数返回B函数,这就是闭包。而往往面试官想要听到的并不是这样的
Dax Dax
3年前
JS核心原理理解闭包
前置概念在正式看闭包之前,我们先来学习一下前置知识,那就是JS中的作用域,我们知道,在ES5之中,作用域分为两种:全局作用域和函数作用域,随着ES6的到来,新增了块级作用域,想更好的理解闭包,那么搞清楚作用域是首要条件全局作用域我们知道,对于变量而言,我们一般会分成两类:全局变量和局部变量,一般定义在最外围环境的为全局变量,定义在函数当中的为局部变量,在we
Jacquelyn38 Jacquelyn38
3年前
你不可不知的JS面试题(第三期)
1、什么是闭包?如图所示,闭包就是一个定义在函数内部的函数,其作用是将函数内部和函数外部连接起来。大家知道,作用域的问题,就是在函数内部定义的变量称为局部变量,外部取不到值。下面我们通过代码来更加详细地看一下:function A()       let x  1;       return function B()           c
Bill78 Bill78
3年前
Python 中的闭包
闭包定义:如果在一个内部函数里,对在外部作用于(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包Python中的闭包原文出处:田小计划(http://www.cnblogs.com/wilber2013/p/4658894.html)闭包(closure)是函数式编程的重要的语法结构
Wesley13 Wesley13
3年前
JS 闭包(内存溢出与内存泄漏)(垃圾回收机制)
1.有关闭包定义闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量闭包的特性:函数内再嵌套函数内部函数可以引用外层的参数和变量参数和变量不会被垃圾回收机制回收
Easter79 Easter79
3年前
Swift讲解专题八——闭包
Swift讲解专题八——闭包一、引言      Swift中的闭包是有一定功能的代码块,这十分类似于ObjectiveC中的block语法。Swift中的闭包语法风格十分简洁,其作用和函数的作用相似。二、从一个系统函数看闭包      Swift标准函数库中提供了一个sort排序函数,对
Stella981 Stella981
3年前
JavaScript函数——闭包
闭包概念只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁例子functionouter(){varlocalVal30;returnlocalVal;}
Wesley13 Wesley13
3年前
go 学习笔记之10 分钟简要理解 go 语言闭包技术
闭包是主流编程语言中的一种通用技术,常常和函数式编程进行强强联合,本文主要是介绍Go语言中什么是闭包以及怎么理解闭包.如果读者对于Go语言的闭包还不是特别清楚的话,可以参考上一篇文章go学习笔记之仅仅需要一个示例就能讲清楚什么闭包(https://www.oschina.net/ac
Easter79 Easter79
3年前
Swift3.0 闭包(blcok)的全面介绍及使用
闭包是自包含的函数代码块,可以在代码中被传递和使用。Swift中的闭包与C和ObjectiveC中的代码块(blocks)以及其他一些编程语言中的匿名函数比较相似。闭包可以捕获和存储其所在上下文中任意常量和变量的引用。被称为包裹常量和变量。Swift会为你管理在捕获过程中涉及到的所有内存操作。闭包表达式语法有如下的一般形式:
Stella981 Stella981
3年前
Golang闭包案例分析与普通函数对比
闭包案例packagemainimport("fmt""strings"//记住一定引入strings包)//①编写一个函数makeSuffix,可以接收一个文件后缀名(比如.jpg),并返回一个闭包//②调用闭包,可以传入一个文件名,如果该文件名没有指