最近小咸儿在学习JavaScript的时候,认识了一个新朋友,名字叫做“闭包”,接下来我就给大家介绍一下她。
叫什么
闭包:闭包就是能够读取其他函数内部变量的函数。在JavaScript中,只有函数内部的子函数才能读取局部变量,在一定程度上也可以理解为‘定义在一个函数内部的函数’,在本质上:闭包是将函数内部和函数外部连接起来的桥梁。
更详细的内容请见:闭包-百度百科;闭包-JavaScript |
面目
var foo2 = (function () { //沙箱,自己调用自己
//闭包的位置
var num = "幽灵";
return function () {
};
})();
亲朋好友
在看到闭包的真面目之后,她的一些亲朋好友也要相继亮相,例如:亲戚A:作用域(scope);亲戚B:作用域链(scope chain);亲戚C:函数的执行环境(execution context);亲戚D:活动对象(call object);朋友小a:沙箱;
在这里,小咸儿就不对这些亲朋好友多做叙述了,大家可以期待一下小咸儿接下来的分享。
小栗子
讲述了这么多,不如一个小栗子实在:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
<meta charset="utf-8" />
<script type="text/javascript">
//1 1 2 3
//第n项是第n-1和n-2的和,开始的两项为1
var count1 = 0;
var fib1 = function (n) {
count1++;
if (n == 0 || n == 1) {
return 1;
}
return fib1(n - 1) + fib1(n - 2);
};
//fib1(11); //287
//fib1(12); //465
//fib1(13); //753
//alert(count1); //很损耗性能
//利用闭包,先存一部分数据,提高性能
/*
var foo1 = function () { };
var foo2 = (function () { //沙箱,自己调用自己
//闭包的位置
var num = "幽灵";
return function () {
};
})();
*/
var count2 = 0;
var fib2 = (function () { //沙箱
var arr = [1, 1];
return function (n) {
count2++;
/*
if (arr[n]) {
//不存在,返回
} else {
//存在,递归
}
*/
var res = arr[n];
if (res) {
return res;
} else {
arr[n] = fib2(n - 1) + fib2(n - 2);
return arr[n];
}
};
})();
/* 显示10个斐波那契数
for (var i = 0; i < 10; i++) {
alert(fib1(i)+","+fib2(i));
}
*/
//相比之下,闭包的效率要高很多
//fib1(11); //287
//fib2(11); //21
//fib1(12); //465
fib2(12); //23
//fib1(13); //753
//alert(count1);
alert(count2);
</script>
</head>
<body>
</body>
</html>
劣势
看到闭包能够提高效率的同时,她也是有不足的地方,就不怕把自己的缺点显示出来:
- (1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
- (2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
总结
在学习的过程中,不仅要学会闭包的高效率,也要注意闭包的劣势,并且将自己的学习劣势不断地转化成自己的优势。