所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。
关于闭包,最简单的描述就是 ecmascript 允许使用内部函数--即函数定义和函数表达式位于另一个函数的函数体内。而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数和声明的其他内部函数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。也就是说,内部函数会在外部函数返回后被执行。而当这个内部函数执行时,它仍然必需访问其外部函数的局部变量、参数以及其他内部函数。这些局部变量、参数和函数声明(最初时)的值是外部函数返回时的值,但也会受到内部函数的影响。
简而言之,闭包的作用就是在out function执行完并返回后,闭包使得javascript的垃圾回收机制gc不会收回out function所占用的资源,因为out function的内部函数inner function的执行需要依赖out function中的变量。
闭包的两个特点:
1、作为一个函数变量的一个引用 - 当函数返回时,其处于激活状态。
2、一个闭包就是当一个函数返回时,一个没有释放资源的栈区。
例1:
<script type="text/javascript">
function setupsomeglobals() {
// local variable that ends up within closure
var num = 666;
// store some references to functions as global variables
galertnumber = function() { alert(num); }
gincreasenumber = function() { num++; }
gsetnumber = function(x) { num = x; }
}
</script>
<button onclick="setupsomeglobals()">生成 - setupsomeglobals()</button>
<button onclick="galertnumber()">输出值 - galertnumber()</button>
<button onclick="gincreasenumber()">增加 - gincreasenumber()</button>
<button onclick="gsetnumber(5)">赋值5 - gsetnumber(5)</button>
例2:
<script type="text/javascript">
function newclosure(somenum, someref) {
// local variables that end up within closure
var num = somenum;
var anarray = [1,2,3];
var ref = someref;
return function(x) {
num += x;
anarray.push(num);
alert('num: ' + num +
' nanarray ' + anarray.tostring() +
' nref.somevar ' + ref.somevar);
}
}
var closure1 = newclosure(40, {somevar:' never-online'})
var closure2 = newclosure(99, {somevar:' bluedestiny'})
closure1(4)
closure2(3)
</script>
例3:
<script language="javascript">
/* 声明一个全局变量 - getimginpositioneddivhtml - 并将一次调用一个外部函数表达式返回的内部函数赋给它。
这个内部函数会返回一个用于表示绝对定位的 div 元素包围着一个 img 元素 的 html 字符串,这样一来,
所有可变的属性值都由调用该函数时的参数提供:
*/
var getimginpositioneddivhtml = (function(){
/* 外部函数表达式的局部变量 - buffar - 保存着缓冲数组。这个数组只会被创建一次,生成的数组实例对内部函数而言永远是可用的
因此,可供每次调用这个内部函数时使用。
其中的空字符串用作数据占位符,相应的数据
将由内部函数插入到这个数组中:
*/
var buffar = [
'<div id="',
'', //index 1, div id 属性
'" style="position:absolute;top:',
'', //index 3, div 顶部位置
'px;left:',
'', //index 5, div 左端位置
'px;width:',
'', //index 7, div 宽度
'px;height:',
'', //index 9, div 高度
'px;overflow:hidden;\"><img src=\"',
'', //index 11, img url
'\" width=\"',
'', //index 13, img 宽度
'\" height=\"',
'', //index 15, img 调蓄
'\" alt=\"',
'', //index 17, img alt 文本内容
'\"><\/div>'
];
/* 返回作为对函数表达式求值后结果的内部函数对象。
这个内部函数就是每次调用执行的函数
- getimginpositioneddivhtml( ... ) -
*/
return (function(url, id, width, height, top, left, alttext){
/* 将不同的参数插入到缓冲数组相应的位置:
*/
buffar[1] = id;
buffar[3] = top;
buffar[5] = left;
buffar[13] = (buffar[7] = width);
buffar[15] = (buffar[9] = height);
buffar[11] = url;
buffar[17] = alttext;
/* 返回通过使用空字符串(相当于将数组元素连接起来)
连接数组每个元素后形成的字符串:
*/
return buffar.join('');
}); //:内部函数表达式结束。
})();//自调用
alert(getimginpositioneddivhtml);//显示返回的函数
alert(getimginpositioneddivhtml("img.gif","img",100,50,0,0,"test"));
</script>
说明:其中的关键技巧在于通过执行一个单行(in-line)函数表达式创建一个额外的执行环境,而将该函数表达式返回的内部函数作为在外部代码中使用的函数。此时,缓冲数组被定义为函数表达式的一个局部变量。这个函数表达式只需执行一次,而数组也只需创建一次,就可以供依赖它的函数重复使用。
以上就是javascript的闭包是什么?javascript闭包如何使用?的详细内容。