javascript闭包,你大爷永远是你大爷

闭包 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时说,闭包,在其余语言中,有的有,有的没有


通常来讲,一个函数在执行开始的时候,会给其中定义的变量划份内存空间保存,以备后面的语句所用,等到函数执行完毕返回了,这些变量就被认为是无用的了.对应的内存空间也就被回收了.下次再执行此函数的时候,全部的变量又回到最初的状态,从新赋值使用.

可是若是这个函数内部又嵌套了另外一个函数,而这个函数是有可能在外部被调用到的.而且这个内部函数又使用了外部函数的某些变量的话.这种内存回收机制就会出现问题.若是在外部函数返回后,又直接调用了内部函数,那么内部函数就没法读取到他所须要的外部函数中变量的值了.因此js解释器在遇到函数定义的时候,会自动把函数和他可能使用的变量(包括本地变量和父级和祖先级函数的变量(自由变量))一块儿保存起来.也就是构建一个闭包,这些变量将不会被内存回收器所回收,只有当内部的函数不可能被调用之后(例如被删除了,或者没有了指针),才会销毁这个闭包,而没有任何一个闭包引用的变量才会被下一次内存回收启动时所回收.


这一段,便是原理,也是实现,(更是核心关键,理解了这个,就理解了闭包。)


用大白话,第一人称的说话法是,我函数是大爷,我函数在定义时,所用的变量,你必须都给我找地方存好了,就存一份就行,爷儿我被调用的时候,就要用这些变量!记作:你大爷永远是你大爷!补充:存的并非这个变量声明之时的快照,而是这些变量,在闭包函数执行时,变量中所存的真实值


函数的参数,在这个函数每次被调用之时,参数也是开出一个内存空间去存的


看个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

用闭包,就搞定了


前端开发必须知道的JS(二) 闭包及应用

www.cnblogs.com/ljchow/arch…


PS : 沸水理论,简版,一壶水,只有烧到100度才能去喝,你每次都只烧到80度就不烧了,那么你永远也喝不上这水,学习也是同样,快要学透闭包了,就停下来不学,那么永远也不可能真正撑握闭包,不可能在工做中,为所欲为的去使用闭包。


学到此,你应该已是沸水100度了!


写的很差,请你们多批评:)

相关文章
相关标签/搜索