javascript——作用域与闭包
http://www.cnblogs.com/lucio-yr/p/4047972.html
一、作用域:
- 在函数内部:用 var 声明的表示局部变量,未用var的是全局变量。
- 作用域取决于变量定义时,而不是执行时。
例1:
1 var a=123; //全局变量 2 function f() 3 { 4 document.writeln(a +'</br>'); //(1) 5 var a=1; //局部变量 6 document.writeln(a +'<br/>'); //(2) 7 } 8 f();
结果如下:
注:在(1)处虽然局部变量 a 尚未定义,而外面的全局变量已经定义,但在函数f内部,局部变量本身已经存在本地空间,因此 (1)处访问的 a 是局部变量。
例2:
1 function f1(){var b=1;return f2();} 2 function f2(){return b;} 3 f1(); 4 var b=2; 5 f1();
注: f2 中的 b 未定义,而 f1 中的 b 是局部变量,因此 函数 f1 与 f2 之间的变量是不可相互访问的。当定义全局变量 b=2 后,此时执行 f1 中的 b 与全局变量 b 是两个不同的变量, f2 中的 b 实际上操作的是全局变量。
可以将函数 f1 中的变量声明为全局变量。如下:
二、闭包:在外部访问内部局部变量
例1:
1 function f() 2 { 3 var b='b'; 4 return function(){ return b;}; 5 } 6 var n=f(); 7 n(); "b"
或
函数 f 中的变量 b 是一个局部变量,外界原本是无法获取的,通过将一个函数的引用传递出去,使外界获得访问内部的权限,如下图,变量 n 指向了内部函数,而内部函数与变量 b 同属于函数 f ,自然可以有效的访问变量 b 。当然有一部分人可能会说 n 本身就是函数而不是变量,这里就是仁者见仁智者见智了。
例2:
如果一个函数需要在其父级函数返回之后留住对父级作用域的链接的话,就必须为此建立一个闭包,务必注意的是在(1)处,绑定的是作用域本身,而不是每个变量的值,如果后面变量 arg 发生变化,则执行 n 时,获取的都是最新值。它使用的值是从执行环境中获取的。
例3:
1 function funct() 2 { 3 var a=[]; var i; 4 for(i=0;i<3;i++) 5 { 6 a[i]=function(){ return i;}; 7 } 8 return a; 9 }; 10 var a=funct(); 11 a[0](); //3 12 a[1](); //3 13 a[2](); //3
如上所示,数组 a 的元素在循环中仅仅是保存了一个函数的引用,这些函数并没有执行。闭包并不记录向数组赋值时对立的 i 值,在循环完后,i 变为了3,当当执行这些函数时,函数采取查找变量 i ,获取的 i 是最新值,也就均是相同的3.
修改如下:
1 function funct() 2 { 3 var a=[]; var i; 4 for(i=0;i<3;i++) 5 { 6 a[i]= 7 ( 8 function(x) 9 { 10 return function(){ return x;}; //(1) 11 } 12 )(i); // 立即执行 13 } 14 return a; 15 }; 16 var a=funct(); 17 a[0](); //0 18 a[1](); //1 19 a[2](); //2
在(1)处,当 i 为1时,则相当于 a[1]=function(){return 1;}。