我理解的函数的作用域链是向外扩张的,即函数中所能访问的变量按照层级关系是由内向外的,每个函数最先能访问的变量是它本身所在的环境的变量,其次下一个能访问的变量就是包含当前的函数所在的环境,然后是下下个包含环境。这样一层层的找下去,直到找到全局执行环境为止。如下图:
在这里,当执行到func1函数的时候,会报错找不到c,是因为c是在func2函数里面定义的,func1函数只能向外寻找c的值,不能向内访问到func2函数的变量,所以找不到c。闭包就可以解决这一问题。
闭包在JavaScript高级程序设计(第3版)中是这样描述:闭包是指有权访问另一个函数作用域中的变量的函数。
我个人的理解更多是 :是指外部函数有权访问内部函数作用域中的变量的函数,(不知道这样理解对不对,先这么记一下,以后要是有不同的理解再做更新)
1. 可以在函数的外部访问到函数内部的局部变量。
2.使用函数内部的变量在函数执行完后, 仍然存活在内存中(延长了局部变量的生命周期),不会随着函数的结束而自动销毁。
1.函数嵌套
2.内部函数引用了外部函数的数据(变量/函数)
3.执行外部函数
1 function fn1() {
2 //此时闭包就已经产生了(函数提升, 内部函数对象已经创建了)
3 var a = 2
4 function fn2 () {
5 a++
6 console.log(a)
7 }
8 // var fn2 = function () { //若是这样写要等这行执行完闭包才产生,函数定义执行
9 //
10 // }
11 return fn2
12 }
13 //fn1() //若是这样执行,第一次执行完成以后闭包就不再存在
14 var f = fn1()
15 f() // 3
16 f() // 4
17 f = null //不再引用,闭包死亡(包含闭包的函数对象成为垃圾对象)
这是一个典型的闭包,fn2嵌套在fn1里面,fn2引用了fn1的局部变量a,执行了fn1函数,并且fn1函数想要打印fn2函数计算的a的结果。我当时看到不理解的地方主要是为啥有var f = fn1() ,这行它的作用是什么?
1、为什么要把fn1函数赋值给f呢?
首先要直到fn1函数要做什么,我把fn1函数打印了一下,结果是
可以看到fn1函数只是要返回一个fn2函数,具体的fn2函数里面要输出什么内容是不管的,所以直接调用并不会打印任何内容。
其次若是直接以fn1()这样的形式调用函数的话,在第一次执行完所有的局部变量就被销毁了,闭包就不存在了
把fn3的这个函数对象赋值给f,f就引用了fn3这个函数对象,当执行完第十四行也就是 var f = fn1()的时候fn3变量就会被释放,但是函数对象还存在,因为有f指向了它,这样说可能不好理解,看图吧,这样就很清楚了
这样就很清楚了,被引用的a变量也会存在于内存中,执行f(),就是在执行fn3,所以依次输出3,4
当我们不再使用的时候就让它等于null,进行释放,以免造成内存泄漏。
原文:https://www.cnblogs.com/lyt0207/p/12039934.html