彻底征服闭包定义,特点,价值,用法!

来源:互联网 发布:大数据搜索引擎技术 编辑:程序博客网 时间:2024/06/06 10:48

闭包的定义与含义

闭:是指闭包的内部环境对外部不可见。
闭包具有控制外部域的能力,也就是可以访问外部环境的执行域,,同时又能防止外部域对闭包的反向控制,也就是说,闭包的领域是对外封闭的。

闭包的实现方法

JS闭包是通过function实现的

闭包的特权

闭包内声明的变量,闭包外的任何环境都无法访问。

举个栗子:

function f1(){     var a=10;     var b=20;     function f2(){          console.log(a);     };     return f2;}var result =f1();result();

这里的闭包是f1函数,不懂没关系,下面我会运用这个例子上面写的知识来去解释为什么f1是闭包。

在上面的代码中,函数f2就被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的,但是反过来就不行,f2内部的局部变量对f1就是不可见的。
既然f2可以读取f1中的局部变量,那么只要把f2作为返回值,我们就可以在f1外部读取它的内部变量!
这种函数叫称之为闭包函数。
所以,这个困扰初学者到底哪个是闭包的问题也就解决了,顺着这个思路你就会发现变量a和变量b也是闭包的一部分,因为他们对外不可见。
所以这个代码例子的闭包部分是

var a=10; var b=20;function f2(){};

JS垃圾回收机制

这里为了让小伙伴们更好的理解闭包,我顺带把JS垃圾回收机制说一下,尽量用通俗简单的话语解释。
一句话定义:
JS垃圾回收机制规定:当你调用完一个函数后,他就不存在了

举个栗子:

function aaa()  {                var a =1;                }aaa();

上面这段代码当函数aaa调用完【aaa();这句就是指函数调用】,那么变量a也就不存在了,它所占的内存就被JS垃圾回收机制给回收了。

那么怎样才能不能JS垃圾回收机制回收呢?也就是让变量a在内存中呆的时间久一点,别一执行完函数就消失了。

解决这个问题就是要运用闭包的特性。

闭包的特点

函数嵌套函数

内部函数可以引用外部函数的参数和变量,这样就会使参数和变量不会被垃圾回收机制所收回

举个栗子:

function f3(a){                var b=1;                function f4(){                    alert(a);                    alert(b);                             }              }

上面栗子可以看出,函数f4内部引用了外部函数f3的参数a和局部变量b
这样函数执行完以后,参数和变量都不会被垃圾回收机制回收。

下面再看一个栗子【首先说明,下面这个栗子很明显不是闭包】

function aaa(){                    var a =1;                    a++;                    console.log(a);              }aaa();aaa();

上面代码的执行结果如图:
这里写图片描述

调用两次的结果都是2,变量a并没进行累加,说明在调用第一次函数aaa后,变量a【值为2】已经销毁了,第二次调用后,变量a又会重新从1加到2进行输出。

var b =1;function bbb(){                b++;                console.log(a);              }bbb();bbb();

调用两次的结果:第一次是2,第二次是3,为什么呢,因为变量b是全局变量,是定义在全局作用域下的【简单点解释就是全局变量,做大的一个作用域】当函数bbb执行完后,虽然函数bbb里的东西销毁了,但是在全局作用域中,变量b还存在,就导致了变量b没有被销毁,继续存在,于是就会一直累加。从这里再次对比上一个栗子,变量a是局部变量,也没有在外部域存在,所以执行完函数aaa后,就会被销毁。

那么如何才能既让a是局部变量,又能让a累加呢?

这就是闭包最拿手的事情!!

栗子如下:

function aaa() {                    var a = 1;                    return function() {                        a++;                        console.log(a);                    }                }                var c = aaa();                c();                c();                alert(a);

执行完以后显示如图:
这里写图片描述

第一次调用结果为2,第二次调用结果为3,成功实现了既让a是局部变量,又能让a累加的功能。同时你看到了上面,变量a未定义,对,你没有看错,我在全局作用域中了加了一句alert(a),结果表明外部域是无法访问到内部域的变量a的。现在是不是有点慢慢通窍了,有种茅塞顿开的感觉了吧。

最后用一句话定义闭包:
函数内在包含子函数,并最终return子函数。

function f1(){     var a=10;     var b=20;     function f2(){          console.log(a);     };     return f2;}var result =f1();result();

闭包函数的最大价值在于:我们可以在函数(f2)的外部(即子函数也就是f2函数),直接读取该函数的局部变量。

再深入研究,就会发现f1()函数就如同一个“类”,而其定义的局部变量就如同该“类”的全局变量;而子函数f2()函数,则如同这个“类”的方法,可以直接使用这个“类”的全局变量n

闭包到底有什么用?

1、缓存:显而易见,就是可以实现数据缓存,我们可以把一个需要长期用到的变量设为闭包函数的局部变量,在子函数里面直接使用它。因此局部变量只定义初始化一次,但我们可以多次调用子函数并使用该变量。这比起我们在子函数中定义初始化变量,多次调用则多次初始化的做法,效率更高。闭包函数常见的一种用途就是,我们可以通过此实现计数功能。在闭包函数定义一个计数变量,而在子函数中对其进行++的操作。这样每次调用闭包函数,计数变量就会加1。

2、实现封装:如前面所说,闭包函数就如同一个“类”,只有在该闭包函数里的方法才可以使用其局部变量,闭包函数之外的方法是不能读取其局部变量的。这就实现了面向对象的封装性,更安全更可靠。

闭包的知识我先说到这里,虽然有一些很重要的细节我没有说,比如,怎么改进这个闭包的书写形式来达到更好的模块化,其实是关于函数的知识,我不想在闭包上把很多细节都扯了,这篇文章对于你理解闭包已经没有问题了,毕竟在这个碎片化时间的世界里,一篇文章不能太长,这里其他的知识我先不说了,过几天我写一篇征服JS函数的文章,再结合这个把闭包彻底搞透。

0 0
原创粉丝点击