博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
闭包和一部电影的关系
阅读量:5972 次
发布时间:2019-06-19

本文共 2151 字,大约阅读时间需要 7 分钟。

在网上,关于闭包的文章众多。

MDN文档中说:

闭包是函数和声明该函数的词法环境的组合

很多文章中说:

闭包是指有权访问另一个函数作用域中的变量的函数

还有一篇文章,总结了闭包的四种定义

最后,我决定去请教我的一个经验丰富的同事。

他说:

闭包就是闭着的包子

......

我发现闭包的最大难点,就是没有一个明确的定义。

于是,我去其精华、取其糟粕,写下这篇关于闭包但完全不去定义闭包的文章。

function outter(){    var name = '小强'    function inner(){        console.log(name)    }    return inner}var foo = outter()foo()   // '小强'复制代码

上面这段代码,就是一个闭包。

无论闭包的定义是什么,这段代码基本上是通行的

首先,如果套用这个定义:

闭包是指有权访问另一个函数作用域中的变量的函数

那么,函数inner就是闭包,因为我们知道:

定义在函数内部的函数,是可以访问外部函数的作用域的。

简写一下:

function outter(){    var name = '小强'    function inner(){        console.log(name)    }    inner()}复制代码

这种结构下,inner函数还是有权访问outter函数作用域中的变量的,所以这是不是闭包?

(我也不知道)

上面代码,是一种最常见的函数嵌套。

outter函数执行时,会创建一个属于outter的执行环境及变量对象。

inner函数执行时,又会创建一个inner的执行环境及变量对象。

它们的相同点是:

执行完毕之后,各自的执行环境及变量对象都会被销毁

尽管函数是一等公民,但是它们执行完毕后、变得“没用”,JS很快将它们“灭门”,这就是JS垃圾回收机制。

它们的联系是:

inner函数可以访问到outter函数的变量对象。

变量对象,顾名思义,就是保存该函数自身变量的一个对象。

内部函数保存所有外层函数的变量对象,形成了自己的作用域。

inner函数的作用域,包括自身的变量对象、outter的变量对象和window的变量对象。

为什么要保存别人的变量对象?

因为对自己有用,自身没有的话就可以去用外层的。

可以说,外层函数的变量服务于内部函数。

再回到这种形式:

function outter(){    var name = '小强'    function inner(){        console.log(name)    }    return inner}var foo = outter()foo()   // '小强'复制代码

不同于普通嵌套,

这里当outter函数执行到最后时,将inner函数return了出去。

显然,outter已经执行完毕了,但是它的执行环境及变量对象都被销毁了吗?

并不是。

有一个幸存者,就是**outter函数的变量对象**。

虽然outter函数在return之后,自身已经执行完毕。

但是,因为它return的是嵌套在自己内部的函数inner,并赋值给全局变量foo,这就导致:

  • 一方面,outter函数执行完毕,outter的变量对象理应被销毁

  • 另一方面,inner函数被赋值给全局变量,随时有可能被调用,那它的作用域不应该被破坏,其中的outter变量对象也就不该被销毁

上面已经说过:

内部函数保存所有外层函数的变量对象,形成了自己的作用域

所以,就是因为还有用,所以outter函数的变量对象并没有在outter执行后被销毁,成为幸存者。

最终,当我执行foo()的时候,

尽管outter函数早已执行完毕,但依然可以打印出其变量name的值'帅哥小强'。

而我想到的,是《辛德勒名单》这部电影。

1939年,波兰在纳粹德国的统治下,党卫军对犹太人进行了隔离统治。

这时,德国商人奥斯卡·辛德勒和德军建立了良好的关系,他的工厂雇用犹太人工作,大发战争财。

犹太人遭到了德军的大屠杀,辛德勒目睹了这一切之后十分震撼。

辛德勒让自己的工厂成为集中营的附属劳役营,在那些疯狂屠杀的日子里,他的工厂也成为了犹太人的避难所。

德国战败前夕,屠杀犹太人的行动越发疯狂,辛德勒向德军军官开出了1200人的名单,倾家荡产买下了这些犹太人的生命。

这个电影很有名,如果没看过建议看一下。

同样,在我们的JS世界中:

当一个函数执行完毕,它的执行环境及变量对象也会遭到一场屠杀,即垃圾回收机制。

在这场屠杀中,辛德勒用一份自己工厂员工的名单,使自己的工厂成为集中营的附属劳役营,更成为犹太人的避难所。

inner函数,也有一份自己员工的名单,那就是作用域。

这份名单上,就包含了outter函数的变量对象。

inner函数被赋值给全局变量,就好比辛德勒和德军建立了良好关系,

它的作用域就成为变量对象的避难所,

因为outter函数的变量对象被写在inner函数的员工名单(即作用域)中,所以才免遭杀害。

这就是JS版的《辛德勒名单》。

那么在这个过程中,究竟哪部分属于闭包呢?

转载地址:http://ruzox.baihongyu.com/

你可能感兴趣的文章
android115 自定义控件
查看>>
iOS uuchart 用法
查看>>
c# 多线程 调用带参数函数
查看>>
JQuery 如何选择带有多个class的元素
查看>>
The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar
查看>>
redis主从配置<转>
查看>>
karma如何与测试框架合作2之webpack
查看>>
关于VSCode更新对于emmet2.0支持的配置更改问题。
查看>>
10分钟搭建MySQL Binlog分析+可视化方案
查看>>
vmware虚拟机配置串口
查看>>
小型自动化运维--expect脚本之传递函数
查看>>
Nsrp实现juniper防火墙的高可用性【HA】!
查看>>
oracle11g 安装在rhel5.0笔记
查看>>
解决Lync 2013演示PPT提示证书问题的多种方法
查看>>
bootloader功能介绍/时钟初始化设置/串口工作原理/内存工作原理/NandFlash工作原理...
查看>>
C++ 构造函数与析构函数
查看>>
ssh免密码登录
查看>>
Linux下Django环境安装
查看>>
如何在指定的内容中找出指定字符串的个数
查看>>
我的友情链接
查看>>