一、js变量作用域
js的变量作用域有两种,全局变量和局部变量
需要注意的是,函数内部可以直接读取全局变量。
var global = 666;
function func() {
alert(global);
}
func(); //666
复制代码
函数外部无法读取到函数内部的局部变量,因为函数在执行完之后,函数内部的环境就被销毁了。
function func() {
var message = 888;
}
alert(message); // error
复制代码
如果函数内部没有使用var
,那么实际上就相当于把这个变量声明为全局变量了。
function func() {
message = 999;
}
func(); //这里注意要运行一遍函数,`message` 才有定义
alert(message);
复制代码
二、如何从外部读取到局部变量?
function f1() {
var message = 999;
function f2() {
alert(message); //999
}
}
复制代码
上面的代码中,f2
可以访问到f1
的局部变量message
,那么我们只要把f2
作为f1
的返回值return
出去,那么就可以在外部访问到message
了。
function f1() {
var message = 999;
function f2() {
alert(message); //999
}
return f2;
}
复制代码
三、简单理解闭包
上面的f2
函数就是闭包。
闭包就是能够读取其他函数内部变量的函数,所以,闭包实际上是一个函数。
闭包可以理解为“定义在一个函数内部的函数”,本质上,闭包是将函数内部和外部连接起来的一座桥梁。
这里要注意一点,父函数内部定义的子函数,如果没有引用父函数作用域中的变量,那么这个子函数不是闭包,这点非常重要,也就是说,闭包是由函数和它所在的环境构成的,缺一不可。
四、 闭包的用途
1.读取函数内部的变量 2.让这些变量始终保存在内存中
function f1() {
var n = 999;
nAdd = function() { n += 1 }; //nAdd是一个全局函数
function f2() {
alert(n);
}
return f2;
}
var result = f1(); //result是一个函数,f1中return的字函数
result();//999
nAdd();//执行全局函数
result();//1000
复制代码
理解:按照正常的函数执行,f1
执行完了之后,f1
的变量n
会被销毁,但是上面的n
仍然保留着999的数值,原因是f1
的返回值f2
被赋值给全局变量result
, 而f2
的存在依赖f1
,所以f1
也一直在内存中。
五、使用闭包的注意事项
闭包会让函数中的变量都被保存在内存中,内存消耗大,所以不能滥用闭包,可以在不使用该变量的时候将其delete。
闭包会在父函数外部改变父函数内部的值,如果把父函数当作object使用,把闭包当作公有方法,内部变量当作私有成员,那就要小心不要随意改变父函数内部变量的值。
参考资料: