JavaScript中,由于变量的作用域和生命周期限制,使得局部变量只能在作用域内有效,闭包的出现,使得局部变量的作用域扩大。
函数调用完成之后,其执行上下文环境不会接着被销毁,这便是闭包的核心内容。闭包实现的关键在于:函数作为返回值,函数作为参数传递。
在学习闭包的时候,看到一段代码,实现一个基础计数器的功能。虽然简单,但是这段代码,让我对JavaScript有了更深层次的理解:
<body>
<p>局部变量计数。</p>
<button type="button" οnclick="myFunction()">计数!</button>
<p id="demo">0</p>
<script>
var add = (function () {
var counter = 0;
return function () {return counter += 1;}
})();
function myFunction(){
document.getElementById("demo").innerHTML = add();
}
</script>
</body>
代码示例来自:http://www.runoob.com/try/try.php?filename=tryjs_function_counter3
1.对于“()”:圆括号"()"在JavaScript中,表示立即执行方法/函数,如果没有"()",可以将方法/函数看做一段普通的字符串,有了"()",浏览器(JavaScript解析器)才开始解析这个字符串,把它当做JavaScript方法来执行,也就是调用方法/函数。
2.对于整段代码的执行:
“document.getElementById("demo").innerHTML = add()”中的add(),可以分为两部分来看,“add”和“()”。
(1):“add”部分:
var add = (function () {
var counter = 0;
return function () {return counter += 1;}
})();
最末尾的“()”表示需要执行前面括号中的代码,也就是“function () { var counter = 0; return function () {return counter += 1;}}”,该段代码执行完成,返回的是“function () {return counter += 1;}”。这是一个函数。如果没有地方调用这个函数,那么它也就差不多是一个普通的字符串。那么就涉及到下面说的“add()”后面的圆括号的作用。
(2):“()”部分:表示调用add返回的函数,也就是“function () {return counter += 1;}”。
计数器受匿名函数的作用域保护,只能通过 add 方法修改。闭包使得函数拥有私有变量变成可能。
下面的这段代码,是对作用域以及变量的取值问题有了更清晰的理解:
var x =10;
function fn(){
console.log(x);
}
function show(f){
var x=20;
(function (){
f();
})();
}
show(fn);//结果是10而不是20
对于X的取值:要到创建这个函数的那个作用域中取值——是“创建”,而不是“调用”。
刚开始的时候粗略看代码,觉得"f()",这个函数是什么函数,没有定义,难道不会报错??自己去试了这段代码才发现,show(fn)中,传递的参数是fn,在"function show(f){}"中,fn作为参数传递给show,并且show方法中的匿名函数中,f()是来自show方法的参数,所以这里也是闭包中的“函数作为参数传递”这一实现方式。
请参考更详细的关于闭包的介绍:http://www.cnblogs.com/wangfupeng1988/p/3994065.html