匿名函数与闭包的区别
匿名函数:没有函数名称的函数;
这就是匿名函数:
function(argument1,argument2){
}
闭包:一个可以使用另外一个函数作用域中的变量的函数。
如下面的代码函数b就是闭包,但是这个前提是:当函数a的内部函数b被函数a外的一个变量引用的时候,就创建了一个我们通常所谓的“闭包”。
意思是说b要变成闭包的话,就必须被外包所引用,即c引用:
用一个专业一点的说法就是:函数调用返回后一个没有释放资源的栈区;
一般,当函数执行完毕后,局部活动对象会被销毁,内存中仅保存全局作用域,但闭包的情况是不一样的。闭包的活动对象依然会保存在内存中,于是像上例中,函数调用返回后,变量i是属于活动对象里面的,就是说其栈区还没有释放,但你调用c()的时候i变量保存的作用域链从b()->a()->全局去寻找作用域var i声明所在,然后找到了var i=1;然后在闭包内++i;结果,最后输出的值就是2了;不知道这么说有没人明白,如果不明白,那么只要记住它的闭包的两个点就好了,一点就是闭包的活动对象没有被销毁;第二点是作用域链的关键是他要遇到var 声明;就好了····
共同点:他们都有是函数;除此之外没有任何共同点;
理论上匿名函数和闭包是不一样的概念,在PHP中这两者概念与其他语言(比如JavaScript)是不一样的,这两者在使用上可以视为等同的
匿名函数、lambda表达式、闭包(closure)区别与作用
一.匿名函数、lambda、closure区别
从功能性上说lambda和closure(或是OC中的blocks)是一个东西,只是不同语言的不同称呼罢了,它们都是匿名函数。若匿名函数捕获了一个外部变量,那么它就是一个closure。
二.匿名函数、lambda、closure作用
简单说,引入它们的作用有2个:
简洁
捕获变量
首先说简洁,匿名函数可以在其他函数内部声明与定义,不用另外写个命名函数
自执行的匿名函数
什么是自执行的匿名函数?
它是指形如这样的函数: (function {// code})();
疑问
为什么(function {// code})();可以被执行, 而function {// code}();却会报错?
分析
(1). 首先, 要清楚两者的区别:
(function {// code})是表达式, function {// code}是函数声明.
(2). 其次, js”预编译”的特点:
js在”预编译”阶段, 会解释函数声明, 但却会忽略表式.
(3). 当js执行到function() {//code}();时, 由于function() {//code}在”预编译”阶段已经被解释过, js会跳过function(){//code}, 试图去执行();, 故会报错;
当js执行到(function {// code})();时, 由于(function {// code})是表达式, js会去对它求解得到返回值, 由于返回值是一 个函数, 故而遇到();时, 便会被执行.
另外, 函数转换为表达式的方法并不一定要靠分组操作符(),我们还可以用void操作符,~操作符,!操作符……
如:
!function(){
alert(“另类的匿名函数自执行”);
}();
匿名函数与闭包
闭包的英文单词是closure,这是JavaScript中非常重要的一部分知识,因为使用闭包可以大大减少我们的代码量,使我们的代码看上去更加清晰等等,总之功能十分强大。
闭包的含义:闭包说白了就是函数的嵌套,内层的函数可以使用外层函数的所有变量,即使外层函数已经执行完毕(这点涉及JavaScript作用域链)。
function checkClosure(){
var str = ‘rain-man’;
setTimeout(
function(){ alert(str); } //这是一个匿名函数
, 2000);
}
checkClosure();
这个例子看上去十分的简单,仔细分析下它的执行过程还是有许多知识点的:checkClosure函数的执行是瞬间的(也许用时只是0.00001毫秒),在checkClosure的函数体内创建了一个变量str,在checkClosure执行完毕之后str并没有被释放,这是因为setTimeout内的匿名函数存在这对str的引用。待到2秒后函数体内的匿名函数被执行完毕,str才被释放。
闭包是怎么定义的,该如何理解
闭包本身定义比较抽象,MDN官方上解释是:A closure is the combination of a function and the lexical environment within which that function was declared.
中文解释是:闭包是一个函数和该函数被定义时的词法环境的组合。
看定义好像比较难理解,那就举个经典的例子吧:
function box(){
var a = 10;
function inner(){
console.log(a) ;
}
return inner;
}
var outer = box();
outer();//10
但是看到这里,还是一脸蒙比,到底哪个是闭包?貌似有三个函数呀,一个box,一个inner还有一个outer = box()。
先看这几个函数在结构上有什么关系,box是全局的函数,具有局部变量a,inner是box函数内的局部函数,a对于inner是可以访问的,但无法直接在box外部访问box内部的局部变量a,outer是全局的。
而执行box()后把box内部的inner return了出去,同时在box函数外部用变量outer作为return出去的inner函数的一个接收,可以理解为是box内部inner函数的一个指针引用。
在box函数执行完毕后,内部的inner还被外部的outer引用着,此时的这个outer就是一个闭包。而inner又对a有引用,所以执行outer会打印a的值,这样就能在box的外部访问到内部的变量a了。
闭包的产生跟普通函数的压栈运行不太一样,普通函数运行时先被压住运行栈内存中,运行完后,函数和其内部变量以及function会释放掉,被内存给回收。但是闭包不会被回收,因为闭包是在函数外部对其内部function的一个指针引用,就像把闭包放在了堆中。
所以此处的闭包是box函数内部的inner函数以及inner被定义时的词法环境,并且在执行box()后,有变量在外部引用这个inner,inner被定义时的词法环境就是box函数的私有作用域,这样就跟闭包的定义吻合了。