一.闭包的概念
说的简单一点,一个函数在另一个函数里面定义,这个函数可以访问其父函数的成员(即父函数的局部变量),则内部函数称为闭包。
二.产生闭包的原因
1.JavaScript支持嵌套函数。
2.作用域链(子函数即嵌套函数可以引用当前作用域的变量)的存在。
三.闭包产生条件
1.只有在父函数层面内才会产生闭包。
2.子函数需要用到父函数的一些东西。
3.子函数的子函数若用到最外层函数的局部变量也会产生闭包。
四.闭包注意事项
1.子函数对父函数的局部变量的只是引用其并不是复制。2.父函数每调用一次会产生不同的闭包。3.在循环中需要注意的问题。
4.闭包的存在会使得他不会被垃圾回收机制回收,他会比其他函数占更多的内存,过渡使用闭包可能会导致内存占用过多。可能会导致浏览器崩溃的问题。
五.闭包的好处
1.减少全局变量。2.减少传递给函数的参数。3.封装。
六.闭包的使用
1.使用构造函数法和闭包机制可以达到封装的目的。
2.使用构造函数法和原型机制可以达到继承的目的。
3.使用原型机制和对象成员你可以达到多态覆盖(对象属性和对象方法)
七.关键词汇
1.在函数外声明的变量为全局变量。(用var声明的)
定义在函数外面,为全局变量,它在一个叫做"全局作用域"的区域里面。"全局作用域"只会在浏览器窗口关闭或页面刷新的时候进行关闭。
2.在函数内声明的变量为局部变量。(注:在函数内部没用var声明的也会由于变量提升变成全局变量)
定义在函数内部时叫局部变量,"局部作用域"会在函数被调用的时候创建,而在函数运行结束的时候关闭(并且里面创建的变量跟函数也会被删掉--垃圾回收机制)
3.作用域链
子函数即嵌套的函数可以引用当前作用域中的变量,这实际上是JavaScript语言中的一个结构——作用域链(Scope Chain)。
4.匿名函数
“匿名函数自执行”(function(){})(),一般执行函数是在函数名后面加括号(),这里(function(){})相当于一个表达式,我们在它后面加(); 就相当于执行了这个函数。
5.全局预处理和词法环境
预处理阶段会创建一个词法环境然后把扫描(会扫描的东西包括两个,先扫描用声明的方式创建的函数,再扫描用var定义的变量。在处理函数声明有冲突会覆盖,处理变量有冲突会忽略。)的东西存入词法环境中,在函数预处理阶段会在每调用一次就会产生一个词法环境,然后先扫描函数的参数,再扫描声明式函数再扫描var声明的变量。
以下为闭包在循环中的注意点
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<script>
/*第一*/
function f(){//创建函数
var a=[];//声明一个局部数组
var i;//声明一个局部变量
for(i=0;i<3;i++){//循环遍历数组a(创建了闭包)
a[i]=function (){//即为a[i]=i,且循环012
return i;
}
}
return a;//此时返回的a后,函数f()值为a数组
}
var test=f();//把a数组赋值给test
alert(test[0]());//此时test为数组,故可以访问其中值
alert(test[1]());
alert(test[2]());
//以上希望弹出值为012,但其实不能,因为该处闭包对局部变量i的值只是引用,并不会记录它的值,所以引用其循环最后的值弹出为333,因为循环到3结束。
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<script>
/*第二*/
function f(){
var a=[];
var i;
for(i=0;i<3;i++){
a[i]=(function (x){//创建一个自调用函数(此处为闭包)
return function (){
return x;
}//i作为实参传入那么形参就可以得到i三次循环的值,而x值是闭包本身的,并不存在像i一样只能引用不能记录值的情况,所以x就可以间接得到i的循环值并保存,最后返回a[i]=x(x值为012),此时a[]数组就保存了012这三个值
})(i);//i为每次循环产生的值,此处自调用,所以将i的值(012)作为实参传入
}
return a;
}
var test=f();//由上面可知这次弹出会是012
alert(test[0]());
alert(test[1]());
alert(test[2]());
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<script>
/*第三*/
function f(){
function test(x){
return function (){//原因为通过中间函数将i的值本地化,把i传进函数调用该函数,
//在函数体内通过闭包返回参数值来实现
return x;
}
}
var a=[];
var i;
for(i=0;i<3;i++) {
a[i] = test(i);
}
return a;
}
var res=f();//此时也可以弹出012
alert(res[0]());
alert(res[1]());
alert(res[2]());
</script>
</body>
</html>
浙公网安备 33010602011771号