三分钟理解JS闭包
作者:互联网
先一句话概括:
一个函数内(父)放另外一个函数(子),(子)函数拿到(父)函数的局部变量,(父)函数把(子)函数返回出去,此时(子)函数保留着(父)函数的私有变量,也就是占据着空间。这样,其他函数(隔壁老王)调用这个(子)函数的时候,其他函数(隔壁老王)就可以拿到那个(父)函数的局部变量了,调用一次拿到一次,不管那个(父)函数执行完毕没有。
function a() {
var n = 0;
function inc() {
n++;
console.log(n);
}
return inc;
}
var c = a();
c(); //控制台输出1
c(); //控制台输出2
理解:
看上面的代码,在函数 a() 里面放一个函数 inc() ,inc() 拿到 a() 的局部变量 n 。
然后呢, a() 又把 inc 返回出去。
这样,c = a() ,就相当于 c = inc() [注意:这时候 inc() 是拿到 a() 里面的 n 并且会保留着这个 n ,这个 n 不会随着 a() 销毁而销毁,也就是不会被垃圾回收机制回收]。
这样,c = a() 就相当于 c = inc() ,所以最后两句代码,是调用了两次 c() ,第一次调用 n++ = 1 , 第二次调用 n++ = 2 。
总结:
由于在JS中,变量的作用域属于函数作用域,在函数执行后作用域就会被清理、内存也随之被收回,但是由于闭包是建立在一个函数内部的子函数,由于其可访问上级作用域的原因,即使上级函数执行完,作用域也不会随之销毁,这时的子函数—也就是闭包,便拥有了访问上级作用域中的变量的权限,即使上级函数执行完后,作用域内的值也不会被销毁。
闭包两大用处:
1) 一个是可以读取函数内部的变量;
2) 另一个就是让这些变量的值始终保存在内存中。
闭包的常见场景:
一般回调函数都有闭包的身影,一个 Ajax 请求的成功回调,一个事件绑定的回调方法,一个 setTimeout 的延时回调,或者一个函数内部返回另一个匿名函数,这些都是闭包。简而言之,无论使用何种方式对某个函数内部局部变量进行传递,当闭包函数(子函数)在别处被调用时,都有闭包的身影。
闭包注意的问题:
由于闭包会使得函数中的变量都保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄漏。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
内存泄露:
程序的运行需要内存。对于持续运行的服务进程,必须及时释放不再用到的内存,否则占用越来越高,轻则影响系统性能,重则导致进程崩溃。不再用到的内存,没有及时释放,就叫做内存泄漏。
标签:闭包,局部变量,函数,作用域,三分钟,JS,内存,inc 来源: https://www.cnblogs.com/suihung/p/16206198.html