夺命雷公狗---javascript NO:30 闭包

1、什么是闭包

所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。

 

例1:运行一下代码,得出结论:在全局作用域没有办法直接引用局部变量

 

<!DOCTYPE html>
<html>
<head>
<meta charset=’utf-8′>
<title></title>
</head>
<body>
<script>
function display(){
var i = 10;//局部变量
}
display();
alert(i);  //报错
</script>
</body>
</html>

 

 

原因:1)作用域不允许

2)受到js的垃圾回收影响

 

例2:有没有办法实现在全局作用域中引用局部变量,运行一下代码

 

<!DOCTYPE html>
<html>
<head>
<meta charset=’utf-8′>
<title></title>
</head>
<body>
<script>
function display(){
var i = 10;  //局部变量
function fn(){
alert(‘hello’);
}
return fn;  //返回fn函数的首地址
}
var test = display();  //定义一个test全局变量,实现display进行引用==>var test =fn;
test();  //hello
</script>
</body>
</html>

 

 

通过运行可知,以上代码可以正常弹出hello字符串,那么这是不是和我们js的垃圾回收所冲突呢?答:不冲突,原因如下:

当我们把display函数的返回值赋值给全局test全局变量时,相当于把fn的函数的首地址赋值给test全局变量,那么在全局中就会有一个引用关系引用了局部函数fn,当js垃圾回收机制运行时,发现fn函数受到了全局变量的引用,所以并不会回收局部函数fn,所以以上代码可以正常弹出hello字符串。

 

2、JavaScript中的垃圾回收机制

在内存中有一个引用计数器,如果外部对这块内存有引用,那么引用计数器会自动进行+1操作,当js的垃圾回收机制运行时,如果引用计数器为0,那么会自动回收此内存空间,反之则不清理。

 

3、闭包的小故事

很久很久以前,有一对姐妹:大桃红、小桃红

小桃红穿越到了清朝,见了传说中四阿哥,又和宫中宫女以及福晋以姐妹相称

有一天:四阿哥问小桃红:“你的姐姐是谁?”,答:“大桃红”

 

其实闭包也是这样一个概念。

  • 闭包即 函数定义时,连同其定义环境的上下文,形成一个整体
  • 不管该函数在哪儿运行,其对变量的访问,都要从定义处开始寻找

 

4、我们眼中的闭包函数

1)函数中的函数

2)把内部函数的首地址作为函数返回值

 

5、闭包的作用

1)可以在全局作用域中访问局部变量

 

2)使局部变量一直驻留在计算机的内存中

 

<!DOCTYPE html>
<html>
<head>
<meta charset=’utf-8′>
<title></title>
</head>
<body>
<script>
function display(){
var i = 10;
function fn(){
alert(++i);
}
return fn;
}
var test = display();
test();//11
test();//12
test();//13
test();//14
</script>
</body>
</html>

 

 

注:虽然闭包非常好用且可以让我们访问局部变量,但是不推荐大家使用闭包程序,由于闭包会一直导致局部变量以及闭包不能被JavaScript垃圾回收机制所回收,所以可能会产生内存泄漏,能不用尽量不用,特殊情况除外。

posted @ 2015-12-09 10:23  夺命雷公狗  阅读(223)  评论(0编辑  收藏  举报