谈谈Js闭包的那些事儿
2016-07-10 23:52
495 查看
闭包这个问题吧,说来也奇怪,懂得人吧,觉得这个东西也就那么回事儿,而不懂的人,就觉得讳若莫深。在我的理解中,闭包的使用,是为了解决Js语言中没有块级作用域这一问题的,也就是说,为了避免污染全局作用域,我们不得不尽量将变量的作用域缩小(当然也是为了性能着想,毕竟局部变量的访问速度要比全局变量来得快),据此,闭包这一技术得以诞生,简单地说,闭包就是利用函数内部作用域的特性来模拟块级作用域的一种方法。
怎样使用闭包呢?说句大白话,就是外部函数里面套内部函数,然后将你想要的变量return返回外部函数就好了。是不是有点晕,现在就以代码的形式,好好地给您说道说道:
对于会Js的人,一看就知道test1是f1的局部(私有)变量,而在f1的外部是无法访问的(实际上的内部机制,就是当f1这个方法执行完毕后,test1变量就与其他变量或方法没有任何关系了,当然就会被垃圾回收器当做垃圾处理),那么此时如果我们要访问test1会怎样做呢?通常我们要用return将test1返回给f1,即
上述代码,相信大家应该都能理解。。。这种获取test1的方法,我称为‘一次性读取’。什么叫‘一次性读取’呢?就是说test1只能被我们以这种读取一次,而想要改变test1的值只能在f1内操作完,然后被我们一次性提取,而不是像全局变量那种,可以被我们反复蹂躏。看不明白?那我还是乖乖上代码吧~~~
经过对test1的一番折腾后,发现f1()确实也返回了我们想要的值,但这真正是我们想要的么?显然不是,我们想要的是每执行一次函数,我们想要的值(本例中为test1)应该(像全局变量一样)发生迭代变化,也就是说执行一次f1(),得到的值是20,再执行一次f1(),得到的值应该是42,以此类推。。。。
注意注意。。。。。。重点闭了个包来了。。。。。。
使用闭包只需要将上述函数改造一下:
仔细看看,我们做了什么就使结果发生了改变呢?
我们加了一个匿名函数,
这一步就是我们的核心,当我们执行完,temp = f1()这一步后,实际上是在全局环境中,return(驻留)了一个匿名函数,就相当于我们人为地添加了一段块级作用域,怎么说呢?虽然Js语言是没有块级作用域将变量封装成局部变量的,但Js有函数,我们都知道函数内部就是一段小小的内部作用域,这个作用域里面的变量就是我们俗称的局部变量,这里的匿名函数就为test1模拟了一个块级作用域,使得test1能在全局环境中贮存,这就相当于在全局环境中声明了一个全局变量test1。
这里需要提醒,刚开始使用闭包的新手们,var temp = f1();是不可少的,如果你图省事,直接就
alert(f1()); //==>20
alert(f1()); //==>20
得到结果就是你创造两个独立的匿名函数区块,这里的test1就不能迭代使用了。
补充一个新知识点就是let关键字,它有什么用呢?简单明了的说,它的出现就是为了代替闭包的ps:仿佛听到了广大Js代码工作者的心声~~~上帝啊~~~。let的作用就是为变量隐式提供一个块级作用域,奉上代码:
最后再说一句,let虽好用,可不要贪杯哦,因为不是所有浏览器都叫特仑苏。。。哦不对,是不是所有浏览器都支持let。
完结!
怎样使用闭包呢?说句大白话,就是外部函数里面套内部函数,然后将你想要的变量return返回外部函数就好了。是不是有点晕,现在就以代码的形式,好好地给您说道说道:
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。
完结!
相关文章推荐
- Extjs4.0 最新最全视频教程
- Javascript中toFixed方法的改进
- 5个常见可用性错误和解决方案
- easyui------显示隐藏列功能
- js数组实现图片轮播
- js可突破windows弹退效果代码
- JSP脚本漏洞面面观
- 使用BAT一句话命令实现快速合并JS、CSS
- js显示当前星期的起止日期的脚本
- 爆炸式的JS圆形浮动菜单特效代码
- js select常用操作控制代码
- JS实现不使用图片仿Windows右键菜单效果代码
- 从jsp发送动态图像
- 原生js结合html5制作小飞龙的简易跳球
- js 页面模块自由拖动实例
- js实现小鱼吐泡泡在页面游动特效
- js 提交和设置表单的值
- PHP VBS JS 函数 对照表
- node.js抓取并分析网页内容有无特殊内容的js文件