闭包和一部电影的关系

闭包的定义

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

MDN文档中说:java

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

不少文章中说:github

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

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

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

他说:code

闭包就是闭着的包子对象

......blog

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

因而,我去其精华、取其糟粕,写下这篇关于闭包但彻底不去定义闭包的文章。

做用域和变量对象

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版的《辛德勒名单》。

那么在这个过程当中,你认为哪部分属于闭包呢?

相关文章
相关标签/搜索