JavaScript闭包函数访问外部变量的方法


Posted in Javascript onAugust 27, 2014

闭包是指有权访问另一个函数作用域中的变量的函数,但作用域的配置机制有一个需要注意的地方,即闭包只能取得包含函数中任何变量的最后一个值。

如以下案例:

function create(){
    var arr = new Array();  
 
    for (var i=0; i<10; i++){
        arr[i] = function(){
            return i;
        };  
    }
 
    return arr;
}
 
var c_arr = create();
 
for(var i=0; i<c_arr.length;i++){
    document.write("c_arr["+i+"] = "+c_arr[i]()+"<br />");    
}

执行结果:

JavaScript闭包函数访问外部变量的方法

表面上看,似乎每个函数返回的i值都不相同,比如c_arr[0]的值应该是0,c_arr[1]的值应该是1,以此类推。可结果每个函数都返回10。为什么呢?

因为每个函数的作用域链中保存着create()函数的活动对象,所以它们引用的都是同一个变量i。当for循环结束以后,i的值也就变成10了,此时每个函数都引用保存变量i的同一个变量对象。

 

我们可以通过创建另一个域名函数强制让闭包的行为符合预期,使每个位置对应相应的值。

function create(){
    var arr = new Array();  
 
    for (var i=0; i<10; i++){
        arr[i] = function(num){
            return function(){
                return num; 
            };
        }(i);   
    }
 
    return arr;
}
 
var c_arr = create();
 
for(var i=0; i<c_arr.length;i++){
    document.write("c_arr["+i+"] = "+c_arr[i]()+"<br />");    
}

执行结果:

JavaScript闭包函数访问外部变量的方法

定义了一个匿名函数,并立即执行匿名函数的机过赋给数组,这里匿名函数有一个参数num,也就是最终的函数要返回的值。在调用每个函数时我们传入变量i。由于函数参数是按值传递的,所以就会将变量i的当前值赋值给参数num。而在这个匿名函数内部,又创建并返回了一个访问num的闭包,这样一来arr数组中的每个函数都有自己num变量的一个副本,因此就可以返回各自不同的数值了。

经典例子

我们再来看一个经典的例子,假设页面有一组button标签,我们利用脚本给这组button标签绑定单击事件,并且单击时能弹出这是第几个标签。

<meta charset="utf-8" />
 
<button>第一个</button>
<button>第二个</button>
<button>第三个</button>
<button>第四个</button>
 
 
<script type="text/javascript">
 
var obj = document.getElementsByTagName('button');
for(var i=0;i<obj.length;i++){
    obj[i].onclick = function(){
        alert(i);
    };  
}
 
</script>

点击每一个按钮结果

JavaScript闭包函数访问外部变量的方法

表面上看,似乎单击每一个标签应该弹出不同数字

第一个应该弹出0;

第二个应该弹出1;

以此类推。

可结果是所有按钮都弹出4,显然这不是我们想要的结果。

我们把程序改一下

<meta charset="utf-8" />
 
<button>第一个</button>
<button>第二个</button>
<button>第三个</button>
<button>第四个</button>
 
 
<script type="text/javascript">
 
var obj = document.getElementsByTagName('button');
for(var i=0;i<obj.length;i++){
    obj[i].onclick = function(num){
        return function(){
            alert(num);
        }       
    }(i);       
}
 
</script>

点击第二个

JavaScript闭包函数访问外部变量的方法

点击第四个

JavaScript闭包函数访问外部变量的方法

我们只需要在函数内建立一个匿名函数,同以上案例同理。即可实现匿名函数捕获外部变量i,结果每个按钮弹的i值都不同。

Javascript 相关文章推荐
javascript显示选择目录对话框的代码
Nov 10 Javascript
Javascript 设计模式(二) 闭包
May 26 Javascript
jQuery EasyUI API 中文文档 - ComboTree组合树
Oct 11 Javascript
jQuery ReferenceError: $ is not defined 错误的处理办法
May 10 Javascript
JS组件Bootstrap导航条使用方法详解
Apr 29 Javascript
微信小程序开发之animation循环动画实现的让云朵飘效果
Jul 14 Javascript
使用JavaScript进行表单校验功能
Aug 01 Javascript
JavaScript中的高级函数
Jan 04 Javascript
原生JS实现获取及修改CSS样式的方法
Sep 04 Javascript
angularJs中ng-model-options设置数据同步的方法
Sep 30 Javascript
Angular ElementRef简介及其使用
Oct 01 Javascript
基于js实现数组相邻元素上移下移
May 19 Javascript
JavaScript中switch判断容易犯错的一个细节
Aug 27 #Javascript
JavaScript中使用arguments获得函数传参个数实例
Aug 27 #Javascript
JavaScript中输出标签的方法
Aug 27 #Javascript
JavaScript实现的GBK、UTF8字符串实际长度计算函数
Aug 27 #Javascript
JavaScript实现的使用键盘控制人物走动实例
Aug 27 #Javascript
JavaScript截取字符串的2个函数介绍
Aug 27 #Javascript
JavaScript中判断页面关闭、页面刷新的实现代码
Aug 27 #Javascript
You might like
第六节 访问属性和方法 [6]
2006/10/09 PHP
ucenter通信原理分析
2015/01/09 PHP
Mac环境下php操作mysql数据库的方法分享
2015/05/11 PHP
帝国cms目录结构分享
2015/07/06 PHP
浅析Yii2集成富文本编辑器redactor实例教程
2016/04/25 PHP
Javascript变量函数浅析
2011/09/02 Javascript
JavaScript中判断对象类型的几种方法总结
2013/11/11 Javascript
jQuery实现带滚动线条导航效果的方法
2015/01/30 Javascript
Vue.js组件tree实现省市多级联动
2016/12/02 Javascript
微信小程序 解决请求服务器手机预览请求不到数据的方法
2017/01/04 Javascript
AngularJS 验证码60秒倒计时功能的实现
2017/06/05 Javascript
使用JavaScript进行表单校验功能
2017/08/01 Javascript
10个最优秀的Node.js MVC框架
2017/08/24 Javascript
bootstrap轮播模板使用方法详解
2017/11/17 Javascript
妙用缓存调用链实现JS方法的重载
2018/04/30 Javascript
webpack css加载和图片加载的方法示例
2018/09/11 Javascript
node.js实现带进度条的多文件上传
2020/03/27 Javascript
微信小程序实现侧边栏分类
2019/10/21 Javascript
python模拟登录百度贴吧(百度贴吧登录)实例
2013/12/18 Python
由浅入深讲解python中的yield与generator
2017/04/05 Python
python最长回文串算法
2018/06/04 Python
Django实现文件上传下载
2019/10/06 Python
python实现的分层随机抽样案例
2020/02/25 Python
Python使用plt.boxplot() 参数绘制箱线图
2020/06/04 Python
深入了解NumPy 高级索引
2020/07/24 Python
Python 防止死锁的方法
2020/07/29 Python
使用django自带的user做外键的方法
2020/11/30 Python
CSS3制作hover下划线动画
2017/03/27 HTML / CSS
HTML5有哪些新特征
2015/12/01 HTML / CSS
美国时尚女装在线:Missguided
2016/12/03 全球购物
顶丰TOPPIK台湾官网:增发纤维假发,告别秃发困扰
2018/06/13 全球购物
中国制造网:Made-in-China.com
2019/10/25 全球购物
端午节粽子促销活动方案
2014/02/02 职场文书
国际商务专业毕业生自我鉴定2014
2014/09/27 职场文书
2015年银行工作总结范文
2015/04/01 职场文书
活动总结模板大全
2015/05/11 职场文书