1.Javascript的做用域是函数做用域而非块级做用域闭包
//C语言 #include void main() { int i=2; i--; if(i) { int j=3; } printf("%d/n",j); //use an undefined variable:j }
这是由于c中的做用域是块级的,j是在if后的{ }中定义的,因此没法访问,然而在js中会是什么状况?函数
(function(){ var i=1; if(i==1){ var j=3; } console.log(j); //3 })()
在这里,j是能够访问的,也就是说在一个函数中的任何位置定义的变量在该函数中的任何地方都是可见的code
这里说起一句Javascript的做用域链(scope chain),每一个函数定义时都会将他的做用域链定设为他定义的环境ip
function a(){ function b(){ //code } }
这段代码中,b的环境为a,a的环境为全局(window),在b中查找变量时会先搜索自身函数内部,若是不存在就去a的内部查找,还不存在就去全局中查找,若仍是找不到就是undefined,这就构成一条链ci
2.Javascript中变量的做用域分为全局变量和局部变量作用域
在函数内部能够访问全局变量和函数内的局部变量,而在函数外部访问不到函数内的变量,看代码rem
var p=11; function f1(){ console.log(p); } f1(); //11
function f1(){ var p=11; } f1(); console.log(p); //ReferenceError: p is not defined
经过这俩段代码能够理解全局变量和局部变量,可是定义局部变量时必定要注意加上var,若是不加上其实定义的是一个全局变量,看代码get
function f1(){ p=11; } f1(); console.log(p); //11
3.那如何访问函数内部的变量并对它进行操做呢?这里就须要用到闭包博客
先看看闭包的官方解释:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(一般是一个函数),于是这些变量也是该表达式的一部分io
看到这句户我不由想问,这是个啥?
后来参考了一些博客和《Javascript秘密花园》才开始理解,闭包大概就是函数内部的一个函数被外部调用,这样就能够调用内部变量了,好比下面这段
function f1(){ var p=11; return { increment: function() { p++; }, show: function() { alert(p) } } } var f=f1(); f.show(); //11 f.increment(); f.show(); //12
先看一下控制台,f是什么样的
这里能够看到,f包含increment和show两个函数,而这两个函数是f1的内部函数因此能够访问p这个变量,在我理解,这里的increment和show就是f1()的两个闭包,用他们就能够从外部调用这个变量
4.闭包能够作些什么?
首先我以为能够模拟private,就像上面那段代码,这个变量只能在这个函数内部访问,也只有使用了闭包才能访问
第二,和Javascript的垃圾回收有关,这里我还不是很清楚,等到搞明白了再来补上
5.这里有一个要注意的就是循环中使用闭包的问题,这里借用《Javascript秘密花园》里的一个例子
function f1(){ for(var i = 0; i < 10; i++) { setTimeout(function() { console.log(i); }, 1000); } } f1();
这段代码输出的是10个10而不是指望的0到9,由于闭包内是对i的引用,而后函数执行时i已经变成了10,这里可使用自执行的匿名函数
function f1(){ for(var i = 0; i < 10; i++) { (function(e) { setTimeout(function() { console.log(e); }, 1000); })(i); } } f1();
这里的匿名函数将i做为参数,这里的e会有i的一个拷贝,而引用时是对e的引用,这就避免了上述的问题