闭包 what 's the fuckjavascript
闭包,是什么鬼,谁学谁都脑进水!html
我会用5W3H1TS的方式,去讲闭包前端
1. whatjava
一个函数,记住本身定义时的“词法做用域”,就产生了闭包安全
即便此函数在其余地方执行!闭包
上一个“词法做用域”的 例子 ,程序走起,与JAVA的动态做用域,有本质不一样框架
因果链思惟中,这个词法做用域就是“已知的由于”,经过这个由于,咱们往下想,才能想通,闭包这个结果函数
例子:学习
var fn1;
function aa(){
var t1 = 100;
fn1 = function(){
console.log(t1);
}
}
var t1 = 200;
aa();
fn1();
复制代码
结果是打印 100,ui
结论: 能够肯定,JS真的是词法做用域
我是按“例子-结论”的思惟去作的
2. why
闭包是解决函数式语言的一个问题的一种技术,这个问题就是如何保证将函数当作值创造并传来传去的时候函数仍能正确运行。
闭包实现的例子,其中一种用法: 模拟块做用域,不要全局污染。由于JS只有全局做用域和函数做用域(这话并不彻底对,但先记住,这就是JS让人FUCK的缘由。。。,不像JAVA,很是规矩,让学的人,学起来也能很是清楚,省力)
3. who
JS有的,咱们这里只讨论JS的范畴,宿主环境,JS的引擎。其余语言,有的有,有的没有
4.where
框架中,还有当即执行函数中,JQUERY库,JQ写的小组件
5. when
看下面连接的文章
6. how1
具体用时,要写什么,先上一个小例子
例子:
var result = foo(1)(2);
alert(result);
function foo(a){
return function(b){
return a+b;
}
}
复制代码
很简单,结果为3
再上一个有应用场景的小例子
<html> <title>小例子</title> <meta http-equiv="Content-Type" content="text/html" ; charset="utf-8"> <body onload="myEffect()"> <table id="mytab" border="1"> <tr> <td> 第0行 </td> </tr> <tr> <td> 第1行 </td> </tr> <tr> <td> 第2行 </td> </tr> </table> <div id="console" style="background:#ffff00"></div> </body> <script> function myEffect(){ var console=document.getElementById('console'); var tab=document.getElementById('mytab'); var trs=tab.getElementsByTagName('tr'); for(var i=0;i<trs.length;i++){ trs[i].onclick=(function(){ var rowNum=i; return function(){ console.innerHTML="点击了第"+rowNum+"行"; } })(); } } </script> </html> 复制代码
试试,不去用 var rowNum=i;
而是改成:
trs[i].onclick=(function(){
return function(){
console.innerHTML="点击了第"++"行";
}
})();
复制代码
会发生神马,而后自行体会一下,再往下看
7.how2
实现原理
函数调用是用栈,存变量是用堆(不必定正确,只是比喻,为了方便理解),
函数被调用时,函数
与内存GC机制相关,因此3时说,闭包,在其余语言中,有的有,有的没有
这一段,便是原理,也是实现,(更是核心关键,理解了这个,就理解了闭包。)
函数的参数,在这个函数每次被调用之时,参数也是开出一个内存空间去存的
看个TIME的例子,也是核心例子了!
for(var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i);
}, 1); //1毫秒后,打印
}
复制代码
这个代码,本意是想 打印
0
1
2
3
4
可是,打出来是
5
5
5
5
5
当你知道“你大爷永远是你大爷”的理论后,就会明白,
function() {
console.log(i);
}
复制代码
此函数,所用的i这个变量,是存了一份,找地方放好了,可是这个变量i,他的值却也在变化,因此当此函数用这个变量时,这个变量的值,就变为5了!
要想达到输出,0到4的结果,就要让变量存上一份,而且没有其余程序去改变他,就OK了
下面,提供四个改法,都是用了上面的理论,你们再体会一下
for(var i = 0; i < 5; i++) {
setTimeout((function(ii) {
return function(){
console.log(ii);
}
})(i), 1);
}
复制代码
这是setTimeout内部的函数,去闭包存一份不变的变量法,还能够不用参数去存一份单独的变量
for(var i = 0; i < 5; i++) {
setTimeout((function() {
var ii = i;
return function(){
console.log(ii);
}
})(), 1);
}
复制代码
咱们再来,把单存的变量,放到setTimeout以外
for(var i = 0; i < 5; i++) {
(function(ii) {
setTimeout(function () {
console.log(ii);
}, 1);
})(i);
}
复制代码
同理,也能够不用参数:
for(var i = 0; i < 5; i++) {
(function() {
var ii = i;
setTimeout(function () {
console.log(ii);
}, 1);
})();
}
复制代码
这就是四个例子,核心思想就是让闭包的变量是单独的,不要被别的代码去改变值,这样就能达到想要的目的了,其实就是在内存中建了5个变量,去存这0,1,2,3,4这5个变量的值,在须要的时候,取出来用。
8.tip
优势:
1.保护函数内的变量安全,增强了封装性
2.在内存中维持一个变量(用的太多就变成了缺点,占内存)
缺点
闭包的缺点就是常驻内存,会增大内存使用量,内存浪费,使用不当很容易形成内存泄露,无效内存的产生
9.scene
为了看 复杂的代码时用,本身主动用得少,
藏于框架之中的有,交互响应,写的函数中,传的参数常量,就是闭包,但通常人就当黑盒子看,对使用框架的人来讲,是透明的
id.onclick = function(){ alert(i); } 循环四次,打出来,都是4
用闭包,就搞定了
PS : 沸水理论,简版,一壶水,只有烧到100度才能去喝,你每次都只烧到80度就不烧了,那么你永远也喝不上这水,学习也是同样,快要学透闭包了,就停下来不学,那么永远也不可能真正撑握闭包,不可能在工做中,为所欲为的去使用闭包。
学到此,你应该已是沸水100度了!
写的很差,请你们多批评:)