猫窝私语 — Makumo's Blog

玛酷猫的温馨小窝,记录生活点点滴滴。

@玛酷猫12 年前

09/7
17:47
JS&JQUERY

JavaScript闭包和匿名函数

PS:最近在研究JavaScript的模块化,随手做些笔记吧。

模块化首先要了解两个概念,那就是闭包(closure)和匿名函数(anonymous function)。

关于闭包,网上文章非常多,有位牛人的这篇文章《闭包漫谈(从抽象代数及函数式编程角度)》写的很全面。话说数学相关的知识全都还给大学老师了,好多看不懂。

百度百科的解释:

闭包是可以包含自由(未绑定到特定对象)变量的代码块;这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义。“闭包” 一词来源于以下两者的结合:要执行的代码块(由于自由变量被包含在代码块中,这些自由变量以及它们引用的对象没有被释放)和为自由变量提供绑定的计算环境(作用域)。

话说百科的东西都是文字绕呀绕,把你绕糊涂位置,不看也罢。JavaScript的闭包官方解释:指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。一样文绉绉的,不解其意。套用网络通俗的解释就是“闭包就是能够读/写函数内部的某些变量的子函数,并将这些变量保存在内存中。”,其中两个效果,一是读写函数内部变量,二是常驻内存。

匿名函数是指那些无需定义函数名的函数。匿名函数与 Lambda 表达式(拉姆达表达式)是一回事。唯一的不同——语法形式不同。Lambda 表达式更进一步。本质上,它们的作用都是:产生方法——内联方法,也就是说,省去函数定义,直接写函数体。

引用网络上面一个例子

var baz;
(function() {
	var foo = 10;
	var bar = 2;
	baz = function() {
		return foo * bar;
	};
})();
baz();

尽管在匿名函数外执行,但 baz 仍然可以访问 foo 和 bar。
1,第 1 行,baz 是全局变量;
2,第 2 ~第 8 行,定义一个匿名函数;
3,第 3 和 4 行,foo 和 bar 是匿名函数内的局部变量;第 5 ~ 7 行,在匿名函数内定义一个匿名函数,并将其赋值给全局变量 baz;
4,第 9行,调用 baz。若改成 “alert(baz());”,将显示 20;
5,按理说,在匿名函数外不能访问 foo 和 bar,但是现在可以。
要注意的是,函数内部声明变量时,一定要使用 var 关键字,否则,声明的是一个全局变量。最早自己写代码很少注意这个,也出现过变量被修改的混乱情况。

闭包常用于两种情况,一个是保护函数内的变量安全。函数中foo和bar只有函数baz才能访问,而无法通过其他途径访问到,因此保护了变量的安全性。另一个是在内存中维持一个变量。依然如前例,由于闭包,函数中foo和bar一直存在于内存中。

由于闭包的维持占用内存的特性,频繁使用会大量消耗内存,引起内存泄露。如无特殊需要,尽量不适用闭包,如果使用,当使用完毕后,要记得释放占用的内存。

JavaScript闭包和匿名函数