首先说3点与闭包有关系的东西。
一、变量的作用域
变量的作用域不难理解。
1.函数内部可以访问函数外部的变量,而函数外部不能访问函数内部的变量。
2.如果在函数内定义变量的时候,不加var,那么是全局变量(当然函数要被调用过一次,未调用过则报错:变量未定义)。加var,就是局部变量。
一个示例说明上面两点。
1
2
3
4
5
6
7
8
9
10
|
function f() { p1 = "关羽" ; var p2 = "刘备" ; } window.onload = function (){ f(); //当然,函数必须被调用一次,否则报找不到p1错误了 alert(p1); //关羽 alert(p2); //报错:p2 is not defined } |
二、变量的生命周期
生命周期也不难理解。
1.全局变量生命周期为直到页面被关闭。
2.在函数内通过var关键字声明的局部变量在函数退出后就会失效。
三、匿名函数
这是一个匿名函数
1
2
3
|
setTimeout( function (){ alert(str); //这是一个匿名函数 },2000); |
匿名函数的几种调用形式:
1
2
3
4
5
|
//通过引用调用匿名函数 func1 = function (){ alert( "func1" ); } func1(); |
注意下面3个示例的 () 其实就同func1()这个括号一样,是函数调用符。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
//无引用的调用方式1 ( function (){ }()) //无引用的调用方式2 ( function (){ })() //无引用的调用方式3 void function (){ }(); |
前面的小括号定义匿名函数,后面的小括号调用此匿名函数。记住它的样子喔,不然后面看不懂。
四、闭包
闭包其实说的是这样一种现象:
函数A内部的函数B,被函数A外的变量引用着。函数A内的环境不会销毁(即函数A内的变量永久存在)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
var func1 = function (){ var a = 1; //退出函数,局部变量丢失 alert(a++); } func1(); //弹出1 func1(); //弹出1 var func2 = function (){ var a = 1; var func3 = function (){ alert(a++); } return func3; } var f = func2(); //func2() 必须先调用一次,才能形成闭包 f(); //弹出1 f(); //弹出2其内部的a并没有清空。 |
此处要特别注意的是,要形成闭包,首先必须先调用一次外层函数。
例如上面的 f ,f引用这函数内的函数func3,而func3是可以访问到a的,所以a也可能会被f引用到。只要f不清空,a也不能销毁。
上面的代码是为了方便理解,实际开发中大多使用匿名函数,这样代码量会更少,而且特别适合装逼。
1
2
3
4
5
6
7
8
9
|
var f = ( function (){ var a = 1; return function (){ alert(a++); } })(); f(); //弹出1 f(); //弹出2其内部的a并没有清空。 |
上面就是匿名函数版,创建的时候就调用一次。
五、闭包的作用
1、减少全局变量
通过上面的了解我们知道,闭包能够将局部变量封装永久局部变量,函数调用完毕后依然存在。它能够令一个局部变量永久存在,如数组,自定义的哈希表对象等。封装到局部变量能够减少全局变量,减少被覆盖的可能性。
2、延长局部变量寿命
这点没办法解释了。
参考:javascript闭包