javascript闭包的应用
2015-07-09 10:31
459 查看
我印象中,javascript的闭包属于进阶的范畴,无非是用来在面试中装装逼而已。你看我身边的一个小伙子,有一天我装逼地问他什么是javascript的闭包,他居然连听都没听说过。但他做起前端的东西来很快,就像我见过的其他小伙子一样。
这说明,知不知道闭包,似乎无关重要。
但是,这几天写了一些前端代码,觉得还是应该要了解这个东西。
所谓的闭包,按我的理解,就是一个javascript函数(父函数)里面有子函数,然后外界可以通过这个子函数来访问到父函数里面的变量。闭包的作用在于保护这些父函数里的变量,使得这些变量在父函数运行期结束后,继续存活,免遭javascript垃圾回收机制所回收。
怎么理解呢?举例说明。
比如说,我们在页面上输出一堆列表项,每个列表项都有一个onclick事件:
我们会发现,列表项存在着许多重复代码,造成页面代码很多。如果我们不预先给每个
设置事件,而是在页面加载完毕以后,再给它们绑定onclick事件,这样页面就简洁许多,减少带宽的消耗。
那么,如何绑定事件呢?假如我们这样写:
那么最终,点击每个列表项,都会显示 “我是 100 !”。原因是循环结束后,i是100。
如果换成这样子:
那么就可以得到我们想要的结果。原因是,函数hi(number)中,建立了闭包,在事件绑定的时候,将传过来的i储存起来了。
要理解上述语句,有必要对事件绑定这里做一些说明:
意思是,绑定给元素事件的,是函数定义,而不是一个函数运行语句!一定要清楚这一点。比如说,function hi(numbert){…}是函数定义,hi(i)就是一个函数运行语句。
我们对代码稍加修改,对比来看一下:
在事件绑定的时候,函数hi、hi_bb都执行了。hi里面是普通的执行语句,呼啦啦的一下执行完毕,列表项未能绑定事件;而hi_bb执行后,返回的是函数定义,因此列表项事件绑定成功。
让我们再回顾一下闭包的作用:保护父函数里的变量,使得这些变量在父函数运行期结束后,继续存活,免遭javascript垃圾回收机制所回收。 本文例子中,事件绑定之时,hi_bb执行,i作为参数传入。本来循环语句、页面onload函数结束,i就应该不存在了。但因为hi_bb里有闭包,每一个i的值都保存了下来,在以后的点击事件中,发挥出应有的作用。
这些话好像有些勉强和装逼,我也是在体会中。如果是面向对象语言,这很好理解,对象构造自同一个类,而对象里的属性、变量的值却是不同的。把参数通过构造函数、成员方法,或者属性设置传给对象的属性或成员变量以后,对象就会将它们保存下来。javascript不是面向对象,没有类,只有函数。也许闭包就是它的一种面向对象的模拟。我是这么理解的。
我以前也总结过闭包,现在又写了一篇,感觉又加深了一点理解:
/article/1395735.html
可以在网站 http://jsfiddle.net/ 上运行一下这些代码,加以印证、对照。
这说明,知不知道闭包,似乎无关重要。
但是,这几天写了一些前端代码,觉得还是应该要了解这个东西。
所谓的闭包,按我的理解,就是一个javascript函数(父函数)里面有子函数,然后外界可以通过这个子函数来访问到父函数里面的变量。闭包的作用在于保护这些父函数里的变量,使得这些变量在父函数运行期结束后,继续存活,免遭javascript垃圾回收机制所回收。
怎么理解呢?举例说明。
比如说,我们在页面上输出一堆列表项,每个列表项都有一个onclick事件:
<ul> <li id="li1" onclick="hi(1)">我是1</li> <li id="li2" onclick="hi(2)">我是2</li> ... </ul>
我们会发现,列表项存在着许多重复代码,造成页面代码很多。如果我们不预先给每个
设置事件,而是在页面加载完毕以后,再给它们绑定onclick事件,这样页面就简洁许多,减少带宽的消耗。
那么,如何绑定事件呢?假如我们这样写:
function hi(number){ alert("我是 " + number + " !"); } $(function(){ for(var i = 1;i <= 100; i++){ $("#li" + i).bind("click",function(){ hi(i); }); } });
那么最终,点击每个列表项,都会显示 “我是 100 !”。原因是循环结束后,i是100。
如果换成这样子:
function hi(number){ return function(){//子函数,闭包机制将传入的number存储起来 alert("我是 " + number + " !"); }; } $(function(){ for(var i = 1;i <= 100; i++){ $("#li" + i).bind("click",hi(i)); } });
那么就可以得到我们想要的结果。原因是,函数hi(number)中,建立了闭包,在事件绑定的时候,将传过来的i储存起来了。
要理解上述语句,有必要对事件绑定这里做一些说明:
$("#li" + i).bind("click",函数定义);
意思是,绑定给元素事件的,是函数定义,而不是一个函数运行语句!一定要清楚这一点。比如说,function hi(numbert){…}是函数定义,hi(i)就是一个函数运行语句。
我们对代码稍加修改,对比来看一下:
function hi(number){//函数体内是普通的执行语句 alert("我是急性子 " + number + " !"); } function hi_bb(number){//函数体内返回一个子函数实例 return function(){//子函数,闭包 alert("我是 " + number + " !"); }; } $(function(){ for(var i = 1;i < 3; i++){ //此时hi执行,一次性弹出信息,绑定失败 $("#li" + i).bind("click",hi(i)); //此时hi_bb执行,返回了一个函数定义,绑定成功 $("#li" + i).bind("click",hi_bb(i)); } });
在事件绑定的时候,函数hi、hi_bb都执行了。hi里面是普通的执行语句,呼啦啦的一下执行完毕,列表项未能绑定事件;而hi_bb执行后,返回的是函数定义,因此列表项事件绑定成功。
让我们再回顾一下闭包的作用:保护父函数里的变量,使得这些变量在父函数运行期结束后,继续存活,免遭javascript垃圾回收机制所回收。 本文例子中,事件绑定之时,hi_bb执行,i作为参数传入。本来循环语句、页面onload函数结束,i就应该不存在了。但因为hi_bb里有闭包,每一个i的值都保存了下来,在以后的点击事件中,发挥出应有的作用。
这些话好像有些勉强和装逼,我也是在体会中。如果是面向对象语言,这很好理解,对象构造自同一个类,而对象里的属性、变量的值却是不同的。把参数通过构造函数、成员方法,或者属性设置传给对象的属性或成员变量以后,对象就会将它们保存下来。javascript不是面向对象,没有类,只有函数。也许闭包就是它的一种面向对象的模拟。我是这么理解的。
我以前也总结过闭包,现在又写了一篇,感觉又加深了一点理解:
/article/1395735.html
可以在网站 http://jsfiddle.net/ 上运行一下这些代码,加以印证、对照。
相关文章推荐
- JSTL实现int数据的类型的长度
- javascript闭包的应用
- 【Seajs源码分析】3. 工具方法2
- web server/cgi/html/css/js
- json使用小结
- Extjs.panel.Panel赋值的问题
- JS实现文档加载完成后执行代码
- Json使用Jackson实现子类多态
- js 判断字符是否整数,判断是否是数值
- Hammer.js--转载自李林峰的园子
- js处理title超长问题
- 【CODE】js转换时间格式:将时间转换成自己想要的格式
- js默认行为(也称默认事件)
- javascript+ajax实现产品页面加载信息
- jsrender-for循环中访问父属性
- 浅谈JavaScript中null和undefined
- JavaScript 时间戳和时间相互转换
- 兼容各大浏览器的JavaScript阻止事件冒泡代码
- JS 封装 Map对象
- JS~js里实现队列与堆栈