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 相关文章推荐
js局部刷新页面时间具体实现
Jul 04 Javascript
自己动手手写jQuery插件总结
Jan 20 Javascript
chrome调试javascript详解
Oct 21 Javascript
jQuery Validate表单验证插件 添加class属性形式的校验
Jan 18 Javascript
实例讲解使用原生JavaScript处理AJAX请求的方法
May 10 Javascript
JS制作适用于手机和电脑的通知信息效果
Oct 28 Javascript
Asp.Net之JS生成分页条的方法
Nov 23 Javascript
AngularJs中 ng-repeat指令中实现含有自定义指令的动态html的方法
Jan 19 Javascript
深入理解Javascript中的作用域链和闭包
Apr 25 Javascript
详解如何使用vue-cli脚手架搭建Vue.js项目
May 19 Javascript
使用Dropzone.js上传的示例代码
Oct 10 Javascript
vue3.0 上手体验
Sep 21 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
下载文件的点击数回填
2006/10/09 PHP
php构造函数与析构函数
2016/04/23 PHP
PHP基于堆栈实现的高级计算器功能示例
2017/09/15 PHP
PHP框架实现WebSocket在线聊天通讯系统
2019/11/21 PHP
PHP大文件及断点续传下载实现代码
2020/08/18 PHP
Javascript &amp; DHTML 实例编程(教程)DOM基础和基本API
2007/06/02 Javascript
编写可维护面向对象的JavaScript代码[翻译]
2011/02/12 Javascript
各浏览器对link标签onload/onreadystatechange事件支持的差异分析
2011/04/27 Javascript
JavaScript 函数参数是传值(byVal)还是传址(byRef) 分享
2013/07/02 Javascript
javascript数组操作方法小结和3个属性详细介绍
2014/07/05 Javascript
js用typeof方法判断undefined类型
2014/07/15 Javascript
javascript实现获取cookie过期时间的变通方法
2014/08/14 Javascript
Bootstrap每天必学之栅格系统(布局)
2015/11/25 Javascript
jQuery使用getJSON方法获取json数据完整示例
2016/09/13 Javascript
详解Javascript中的原型OOP
2016/10/12 Javascript
es6在react中的应用代码解析
2017/11/08 Javascript
js操作二进制数据方法
2018/03/03 Javascript
react实现点击选中的li高亮的示例代码
2018/05/24 Javascript
vue.js实现插入数值与表达式的方法分析
2018/07/06 Javascript
vue以组件或者插件的形式实现throttle或者debounce
2019/05/22 Javascript
微信小程序获取当前位置和城市名
2019/11/13 Javascript
Vue 路由间跳转和新开窗口的方式(query、params)
2019/12/25 Javascript
利用Anaconda完美解决Python 2与python 3的共存问题
2017/05/25 Python
Python3常见函数range()用法详解
2019/12/30 Python
python GUI库图形界面开发之PyQt5不规则窗口实现与显示GIF动画的详细方法与实例
2020/03/09 Python
python3 使用openpyxl将mysql数据写入xlsx的操作
2020/05/15 Python
Python如何把字典写入到CSV文件的方法示例
2020/08/23 Python
什么是Python包的循环导入
2020/09/08 Python
CSS图片翻转动画技术详解(IE也实现了)
2014/04/03 HTML / CSS
Javascript如何发送一个Ajax请求
2015/01/26 面试题
工资收入证明样本(5篇)
2014/09/16 职场文书
2015年五一劳动节演讲稿
2015/03/18 职场文书
外出学习心得体会范文
2016/01/18 职场文书
二年级作文之动物作文
2019/11/13 职场文书
利用Pycharm连接服务器的全过程记录
2021/07/01 Python
Android中的Launch Mode详情
2022/06/05 Java/Android