闭包这个问题吧,说来也奇怪,懂得人吧,觉得这个东西也就那么回事儿,而不懂的人,就觉得讳若莫深。在我的理解中,闭包的使用,是为了解决Js语言中没有块级作用域这一问题的,也就是说,为了避免污染全局作用域,我们不得不尽量将变量的作用域缩小(当然也是为了性能着想,毕竟局部变量的访问速度要比全局变量来得快),据此,闭包这一技术得以诞生,简单地说,闭包就是利用函数内部作用域的特性来模拟块级作用域的一种方法。
var f1 = function(){
var test1 = 9;
}
alert(test1 ); //==>error: test1 undefined
对于会Js的人,一看就知道test1是f1的局部(私有)变量,而在f1的外部是无法访问的(实际上的内部机制,就是当f1这个方法执行完毕后,test1变量就与其他变量或方法没有任何关系了,当然就会被垃圾回收器当做垃圾处理),那么此时如果我们要访问test1会怎样做呢?通常我们要用return将test1返回给f1,即
var f1 = function(){
var test1 = 9;
return test1;
}
alert(f1()); //==>9
上述代码,相信大家应该都能理解。。。这种获取test1的方法,我称为‘一次性读取’。什么叫‘一次性读取’呢?就是说test1只能被我们以这种读取一次,而想要改变test1的值只能在f1内操作完,然后被我们一次性提取,而不是像全局变量那种,可以被我们反复蹂躏。看不明白?那我还是乖乖上代码吧~~~
var f1 = function(){
var test1 = 9;
test1++;
test1 += test1;
return test1;
}
alert(f1()); //==>20
alert(f1()); //==>20
经过对test1的一番折腾后,发现f1()确实也返回了我们想要的值,但这真正是我们想要的么?显然不是,我们想要的是每执行一次函数,我们想要的值(本例中为test1)应该(像全局变量一样)发生迭代变化,也就是说执行一次f1(),得到的值是20,再执行一次f1(),得到的值应该是42,以此类推。。。。
注意注意。。。。。。重点闭了个包来了。。。。。。
使用闭包只需要将上述函数改造一下:
var f1 = function(){
var test1 = 9;
return function(){
test1++;
test1 += test1;
return test1;
};
}
var temp = f1();
alert(temp()); //==>20
alert(temp()); //==>42
仔细看看,我们做了什么就使结果发生了改变呢?
我们加了一个匿名函数,
function(){
test1++;
test1 += test1;
return test1;
};
这一步就是我们的核心,当我们执行完,temp = f1()这一步后,实际上是在全局环境中,return(驻留)了一个匿名函数,就相当于我们人为地添加了一段块级作用域,怎么说呢?虽然Js语言是没有块级作用域将变量封装成局部变量的,但Js有函数,我们都知道函数内部就是一段小小的内部作用域,这个作用域里面的变量就是我们俗称的局部变量,这里的匿名函数就为test1模拟了一个块级作用域,使得test1能在全局环境中贮存,这就相当于在全局环境中声明了一个全局变量test1。
这里需要提醒,刚开始使用闭包的新手们,var temp = f1();是不可少的,如果你图省事,直接就
alert(f1()); //==>20
alert(f1()); //==>20
得到结果就是你创造两个独立的匿名函数区块,这里的test1就不能迭代使用了。
补充一个新知识点就是let关键字,它有什么用呢?简单明了的说,它的出现就是为了代替闭包的ps:仿佛听到了广大Js代码工作者的心声~~~上帝啊~~~。let的作用就是为变量隐式提供一个块级作用域,奉上代码:
<html>
<ul>
<li><input type="button" value="0"></li>
<li><input type="button" value="1"></li>
<li><input type="button" value="2"></li>
</ul>
</html>
<script>var input = document.getElementsByTagName('li');var len = input.length;for(let i=0;i<len;i++){input[i].onclick = function(){alert(i);}; } /*这段代码就是一个简单的let应用,将每个按钮的索引值贮存在内存当中,以便点击时显示*/</script>
最后再说一句,let虽好用,可不要贪杯哦,因为不是所有浏览器都叫特仑苏。。。哦不对,是不是所有浏览器都支持let。
完结!