谈谈Js闭包的那些事儿

来源:互联网 发布:opta数据中文 编辑:程序博客网 时间:2024/06/10 16:14

闭包这个问题吧,说来也奇怪,懂得人吧,觉得这个东西也就那么回事儿,而不懂的人,就觉得讳若莫深。在我的理解中,闭包的使用,是为了解决Js语言中没有块级作用域这一问题的,也就是说,为了避免污染全局作用域,我们不得不尽量将变量的作用域缩小(当然也是为了性能着想,毕竟局部变量的访问速度要比全局变量来得快),据此,闭包这一技术得以诞生,简单地说,闭包就是利用函数内部作用域的特性来模拟块级作用域的一种方法


怎样使用闭包呢?说句大白话,就是外部函数里面套内部函数,然后将你想要的变量return返回外部函数就好了。是不是有点晕,现在就以代码的形式,好好地给您说道说道:

var f1 = function(){var test1 = 9;}alert(test1 );    //==>error: test1 undefined

对于会Js的人,一看就知道test1f1的局部(私有)变量,而在f1的外部是无法访问的(实际上的内部机制,就是当f1这个方法执行完毕后,test1变量就与其他变量或方法没有任何关系了,当然就会被垃圾回收器当做垃圾处理),那么此时如果我们要访问test1会怎样做呢?通常我们要用returntest1返回给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());    //==>20alert(temp());   //==>42

仔细看看,我们做了什么就使结果发生了改变呢?

我们加了一个匿名函数,

                       function(){     test1++;     test1 += test1;     return test1;};

这一步就是我们的核心,当我们执行完,temp = f1()这一步后,实际上是在全局环境中,return(驻留)了一个匿名函数,就相当于我们人为地添加了一段块级作用域,怎么说呢?虽然Js语言是没有块级作用域将变量封装成局部变量的,但Js有函数,我们都知道函数内部就是一段小小的内部作用域,这个作用域里面的变量就是我们俗称的局部变量,这里的匿名函数就为test1模拟了一个块级作用域,使得test1在全局环境中贮存,这就相当于在全局环境中声明了一个全局变量test1

这里需要提醒,刚开始使用闭包的新手们,var temp = f1();是不可少的,如果你图省事,直接就

alert(f1());      //==>20alert(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


完结!










0 0