其实js支持函数闭包的主要原因是因为js需要函数能够保存数据。这里的保存数据是只函数在运行结束以后函数内变量的值也会进行保存。至于为什么js需要在函数内可以保存数据,那就是js是一种函数式语言。在函数内保存数据是函数式语言的一大特征。
回顾前面介绍过的三种定义函数方式
functiosu(numnumreturnunum//函数声明语法定义 vasufunction(numnum)returnunum}//函数表达式定义 vasuneFunction("num""num""returnunum")//Functio构造函数
例1:
例2:
例3:
在例1中,我们不能在使用函数声明式语法定义之前调用函数。解决方案:
1.如果使用函数表达式定义函数的话,需要在表达式定义后调用。
2.使用函数声明式。(这里浏览器引擎会 函数声明提升,在所有代码执行之前先读取函数声明)
在例2中,我们预期的结果应该是打印1,实际结果是打印2。
为什么会这样?正因为 函数声明提升 ,所以浏览器在预解析的时候不会判断if条件,直接解析第二个函数定义的时候覆盖了第一个。
解决方案:
在例3中,发现只能只用fun1()调用,而不能使用fun2()调用。
我自己的理解,真正原因不知道。没找到资料。
因为1: function fun3() { }; 等效与 var fun3 = function fun3() { }; 如图:
其实这里我还是有疑问的?哪位大神知道,望告知。
既然,fun2在外面不能调用为什么在函数内部能调用?虽然在debugger还是得不到fun1。
好了,通过上面的三道题目热身。我们继续今天的主题“闭包”。
1.什么是闭包?
我们先从一个示例函数开始:
例1:
例2:
例3:
显然,滥用闭包会增大内存的使用。所以非特殊情况尽量不要使用闭包。如果用到了,记得手动设置空引用,内存才能被回收 f = null ;
图解:(不了解作用域链的同学请先看前面的文章 作用域和作用域链 )
2.什么是匿名函数? (仅仅只是解释这个概念)
如:(即,没有名字的函数)
讲解之前,先清醒下头脑,不要越看越迷糊了。如果迷糊了,那就直接忽略下面的。
obj.fun2();//打印结果"李四"意料之中的。 obj.fun3()();//因为这里返回的是一个函数,所以要再加一对()来调用。打印结果是"张三",意料之外。 //真是百事不得其解啊,什么this指向了全局? 我们前面讲过“ 哪个对象点出来的方法,this就是哪个对象 ”,那我们的 obj.fun3()() 打印的是“张三”也就是说this执行了全局作用域。
我们看看下面的示例也许就知道为什么了。
我们来分解下 obj.fun3()() 先是 obj.fun3() 返回一个匿名函数到了window作用域,然后接着调用this就指向了window了。( 感觉解释有点勉强,也不知道对不,暂时自己先是这么理解的 )
闭包形成的原因:内存释放问题
一般,当函数执行完毕后,局部活动对象会被销毁,内存中仅保存全局作用域,但闭包的情况是不一样的。
闭包的活动对象依然会保存在内存中,于是像上例中,函数调用返回后,变量i是属于活动对象里面的,就是说其栈区还没有释放,但你调用c()的时候i变量保存的作用域链从b()->a()->全局去寻找作用域var i声明所在,然后找到了var i=1;然后在闭包内++i;结果,最后输出的值就是2了;
原文链接:https://www.f2er.com/js/51155.html