javascript闭包学习例子
javascript中的闭包个很让人头疼的概念。总结一下
闭包是指有权访问一个函数作用域中的变量的函数。创建闭包最常见的方式,是在一个函数内部创建另一个函数,用return返回出去。
使用闭包可能造成内存占用不足,尽量少使用。
先看几个例子:
function foo(){
var a = 2; function bar(){
console.log(a);
}
return bar;
}
var baz = foo();
baz(); // 2
bar函数就是一个闭包。调用foo()函数时,得到的是bar函数,赋值给baz。此时,baz就指向内部的bar函数。再调用baz函数,就是调用了内部的bar函数了。
function foo() {
var num = 2;
function bar() {
alert(++num);
}
return bar;
}
var baz = foo();
9 baz(); //3
10 baz(); //4
这和上面的区别是,内部函数变成自加函数,就能说明一些东西了。两次调用,发现它自增,而不是输出相同的数字3,说明了baz函数执行后,num对象没有被销毁,还保存在内存中。
如果没有闭包,那么foo函数执行完后,num对象就要被销毁,但因为闭包的存在,bar函数要访问num对象,所以要把bar函数需要的资源(foo函数)保存在内存中,使其不被销毁。所以输出的是 3 和 4
function foo() {
var num = 2;
function bar() {
alert(++num);
}
bar();
}
foo(); //3
foo(); //3
如果变成这样,那就没有闭包了(return没了)。无论调用几次都输出3,因为函数运行后就被销毁了,不会保存。
看这个例子:
function f1(){
var n=999;
nAdd=function(){n+=1}
function f2(){
alert(n);
}
return f2;
}
var result=f1();
result(); //
nAdd();
result(); //
要说明的是,nAdd()为什么能在外面调用?有两点
1、没有用var ,是一个全局对象,但单有这个还不够。也不能直接在外面调用
2、f1函数必须先执行才能调用nAdd函数,调用了函数就有了闭包,外面就可以访问里面的全局对象或全局方法了。
看这个例子:
有个全局函数叫setTimeout,可以这样使用:
function msg(){
console.log("Message");
}
setTimeout(msg,2000);
两秒后输出:Message
下面我们想给msg传递参数,需要让msg返回一个函数给setTimeout使用,如下:
function msg(m){
return function() {
console.log("Message from: " + m);
}
}
setTimeout(msg("setTimeout"),2000);
两秒后输出:Message from: setTimeout
上面那个是正确版本,msg的参数t作为闭包的一部分绑定给了返回的函数,如果我们这样定义的话就是错误的:
function msg(m){
return function(m) {
console.log("Message from: " + m);
}
}
因为返回了一个带参数“m”的函数,会在setTimeout执行的时候在当前上下文中查找一个叫“m”的变量,而并没有此变量,故得到一个非预期的输出如下:Message from: undefined
闭包可以解决一个最常见的循环调用的例子:一个ul,点击每个li,弹出它的索引值。
var aLi = document.getElementsByTagName('li'); //假设有6个li
for(var i = 0; i < aLi.length; i++){
aLi[i].onclick = function(){
alert(i);
}
}
看起来好像对了,其实结果是:无论你点击哪一个li,弹出的都是6。这是因为for里面的匿名函数没有保存起来,加载网页的时候执行了,循环结束了。点击时,会去寻找变量i,这时循环结束,i是6。
用闭包可以把它保存起来:
var aLi = document.getElementsByTagName('li');
for (var i = 0; i <= aLi.length; i++) {
aLi[i].onclick = (function(i){
return function(){
alert(i);
};
})(i);
}
当点击li时就是调用了闭包函数onclick,使得外部i变量不被销毁,达到目的。
这样也可以解决,通过闭包机制模仿块级作用域
var aLi = document.getElementsByTagName('li');
for(var i=0;i<aLi.length;i++){
(function(i){
aLi[i].onclick = function(){
alert(i);
}
})(i)
}
以上为学习总结,如有错误,望指正
javascript闭包学习例子的更多相关文章
- JavaScript闭包学习笔记
此文都是大牛们关于闭包的观点,在此只是总结. 闭包应用的两种情况即可——函数作为返回值,函数作为参数传递. 1 深入理解javascript原型和闭包 判断一个变量是不是对象非常简单.值类型的类型判断 ...
- javascript 闭包学习
闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域 ...
- javascript闭包学习
(function(){})()===>>>>函数会被立即执行function(){}是一个函数用括号包起来表示是函数表达式再加()表示函数自执行 如何理解闭包?1.定义和用 ...
- javascript 闭包理解例子
function Jquery(){ this.name = 'ysr'; this.sex = 'man'; return { x: this, age : 26 } } var b = new J ...
- JavaScript 闭包的例子
例子出自<<JavaScript权威指南>>, 加上个人的理解和总结, 欢迎交流! /********************************************* ...
- Javascript闭包学习(Closure)
闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 下面就是我的学习笔记,对于Javascript初学者应该是很有用的. 一.变量的作用域 要理解 ...
- JavaScript学习总结(十六)——Javascript闭包(Closure)
原文地址: http://www.cnblogs.com/xdp-gacl/p/3703876.html 闭包(closure)是Javascript语言的一个难点,也是它的特色, 很多高级应用都要依 ...
- [转载]学习Javascript闭包(Closure)
学习Javascript闭包(Closure) 源地址: http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures ...
- ife task0003学习笔记(三):JavaScript闭包
一.this易错分析 在学习闭包的时候,有一个概念this很重要,关于this的理解,下面3种情况:this指向谁? fn.call(obj1); obj2.fn() fn() 答案是obj1 obj ...
随机推荐
- 241. Different Ways to Add Parentheses
241. Different Ways to Add Parentheses https://leetcode.com/problems/different-ways-to-add-parenthes ...
- Ubuntu 中 不显示WIFI解决方法
先用有线接到网络,打开终端,执行以下命令sudo apt-get update sudo apt-get install --reinstall bcmwl-kernel-source 执行成功即可看 ...
- jquery 传递事件的自定义数据
整理一下 1. <script type="text/javascript">$(document).ready(function(){ $("input& ...
- ssh端口转发
http://blog.sina.com.cn/s/blog_47094def0101fvge.html
- 《利用Python进行数据分析》第8章学习笔记
绘图和可视化 matplotlib入门 创建窗口和画布 fig = plt.figure() ax1 = fig.add_subplot(2,2,1) ax2 = fig.add_subplot(2, ...
- kali基本设置
一.更换比较快的软件源 修改sources.list文件(su): leafpad /etc/apt/sources.list #debain源 deb http://mirrors.163.com/ ...
- 微信公共平台开发-(.net实现)2--ACCESSTOKEN值获得
成功的走出第一步后,我们紧接着趁热打铁开始下一步: 成为了开发者之后微信平台会给您AppId和AppSecret,在订阅号中是没有的,所以因该申请一下服务号, 若没有请注意上一篇http://www. ...
- nodejs安装/运行脚本
本文主要介绍nodejs在windows下安装及运行脚本. 安装nodejs 先从nodejs官网:http://nodejs.org/下载对应的系统的安装包,比如用于64位系统的最新0.10.21的 ...
- [Asp.net 开发系列之SignalR篇]专题四:使用SignalR实现发送图片
一.引言 在前一篇博文已经介绍了如何使用SignalR来实现聊天室的功能,在这篇文章中,将实现如何使用SignalR来实现发送图片的功能. 二.实现发送图片的思路 我还是按照之前的方式来讲述这篇文章, ...
- 《Learninghard C#学习笔记》回馈网友,免费送书5本
前言: 在博客园园友的大力支持下,本人的第一本书<Learninghard C#学习笔记>终于出版了. 这本书是本人学习C#的亲身经历,书籍内容都是本人学习过程中认为必须掌握的内容,完全无 ...