一、概念
我理解的闭包其实就是,一个内层函数被一个外层函数所包裹,内层函数引用着外层函数作用域中的变量,当外层函数被调用后,由于其中的变量被内层函数所引用,因此无法被垃圾回收机制所清除,依然占用着内存,从而形成了闭包。
我的理解中,闭包需要满足几个条件
1:有至少两个函数的包裹关系。
2:包裹的母函数需要被调用。
3:内层函数需要引用着外层函数的变量。
二、javascript的特点
其实刚开始接触闭包的时候,还是非常懵的,不知道有什么样的作用,抱着再难也要啃下来的心态,慢慢的发现其实在很多高级的用法当中其实是非常有用的,比如缓存数据,避免全局污染,高阶函数等都有很广的应用。
javascript是有变量作用域概念,也就是说变量分为全局变量和局部变量,我们来看一段代码
var a = '小鹏';
function fun(){
var b = '小明'
console.log(a) // ==> '小鹏'
}
// 其中 a 就是 全局变量 b 就是局部变量
在全局中的变量我们既可以在全局访问到,也可以在函数作用域中,也就是局部中访问的到,但是反过来是不行的,局部的变量,我们在全局是无法访问的。所以这个时候如果我们就想要访问函数内部的变量怎么办?我们可以将函数内部的变量return 出来就可以了。
var a = '小鹏';
function fun(){
var b = '小明'
return b
}
console.log(fun()) // '小明'
三、引入闭包
此时我们就拿到了函数作用域内部的变量,可是还有一个问题,我们的a是暴露在全局下的,由于javascript有一个特点,任意作用域下都可以访问到全局中的变量,也就意味着任意的操作都可能又能力修改,污染全局中的变量,这肯定是不行的,因此,我们可以这样做。
(function(){
var a = '小鹏';
function fun(){
var b = '小明'
}
})()
console.log(a) //Error
这个时候如果我们在全局访问a是会报错的,因为没有声明,而 为其赋值 为 '小鹏' 的那个 a 已经属于函数作用域中的了,我们相当于用一个函数作用域将我们所有需要的变量保护起来,除非通过return 的形式,否则外界是访问不到的,此时我们可以将匿名函数作用域视为一个全局作用域,在这个作用域内部进行处理我们的业务逻辑。如果各位同学认真看过我首篇提到的概念,有没有发现就特别像了,外层函数包裹着内层函数,外层函数被调用,内层函数引用着外层函数的变量,使得 这个 a = '小鹏' 无法在内存中得到释放,因此,形成了闭包。
优势:1:避免全局污染
2:创建可控制的作用域
3:高阶函数 ( 之后的文章会聊到 )
劣势:1:浏览器的垃圾回收机制
我们的浏览器在执行js文件时,会先遍历扫描所有生明的函数和变量,提升到当前作用域最前面,每执行一个函数,都会创建一个执行上下文,当函数执行完之后,便会将这个上下文中的变量销毁掉,以回收内存空间,供下一次使用。而还在被引用着的变量则不会被清楚掉,因此这部分内存就无法释放,长期占据着内存空间。
最后的话:
以上便是我对闭包的一些理解,很多地方还是很粗浅,如果看到这篇博客有异议的地方欢迎评论,以及指正,感谢您的观看了。