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-Mozilla和IE中的一个函数直接量的问题
Jan 09 Javascript
基于jQuery的投票系统显示结果插件
Aug 12 Javascript
面向对象的Javascript之二(接口实现介绍)
Jan 27 Javascript
用IE重起计算机或者关机的示例代码
Mar 10 Javascript
jQuery弹出框代码封装DialogHelper
Jan 30 Javascript
JavaScript计算两个日期时间段内日期的方法
Mar 16 Javascript
微信小程序 获取当前地理位置和经纬度实例代码
Dec 05 Javascript
JavaScript实现AOP详解(面向切面编程,装饰者模式)
Dec 19 Javascript
angular6 利用 ngContentOutlet 实现组件位置交换(重排)
Nov 02 Javascript
vue使用Google地图的实现示例代码
Dec 19 Javascript
jQuery实现checkbox全选、反选及删除等操作的方法详解
Aug 02 jQuery
vue实现图片上传到后台
Jun 29 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
PHP面向对象学习笔记之一 基础概念
2012/10/06 PHP
如何设置mysql允许外网访问
2013/06/04 PHP
PHP采用自定义函数实现遍历目录下所有文件的方法
2014/08/19 PHP
PHP产生不重复随机数的5个方法总结
2014/11/12 PHP
Yii2中使用join、joinwith多表关联查询
2016/06/30 PHP
PHP重定向与伪静态区别
2017/02/19 PHP
PHP将身份证正反面两张照片合成一张图片的代码
2017/04/08 PHP
Laravel第三方包报class not found的解决方法
2019/10/13 PHP
JavaScript实现Sleep函数的代码
2007/03/04 Javascript
JavaScript 类型的包装对象(Typed Wrappers)
2011/10/27 Javascript
javascript进行四舍五入方法汇总
2014/12/16 Javascript
jquery插件orbit.js实现图片折叠轮换特效
2015/04/14 Javascript
微信JS-SDK坐标位置如何转换为百度地图坐标
2016/07/04 Javascript
快速将Vue项目升级到webpack3的方法步骤
2017/09/14 Javascript
浅谈开发eslint规则
2018/10/01 Javascript
vue-loader中引入模板预处理器的实现
2019/09/04 Javascript
5分钟快速看懂ES6中的反射与代理
2019/12/19 Javascript
vuejs中父子组件之间通信方法实例详解
2020/01/17 Javascript
Python ORM框架SQLAlchemy学习笔记之数据添加和事务回滚介绍
2014/06/10 Python
Python中endswith()函数的基本使用
2015/04/07 Python
Python实现的快速排序算法详解
2017/08/01 Python
Python异常原理及异常捕捉实现过程解析
2020/03/25 Python
python多线程和多进程关系详解
2020/12/14 Python
德国柯吉澳趣味家居:Koziol
2017/08/24 全球购物
JD Sports意大利:英国篮球和运动时尚的领导者
2017/10/29 全球购物
工厂保洁员岗位职责
2013/12/04 职场文书
库房主管岗位职责
2013/12/31 职场文书
小学教师师德反思
2014/02/03 职场文书
大学应届毕业生求职信
2014/05/24 职场文书
优秀班主任事迹材料
2014/12/16 职场文书
2015年禁毒宣传活动总结
2015/03/25 职场文书
盗窃罪辩护词范文
2015/05/21 职场文书
导游词之吉林吉塔
2019/11/11 职场文书
2019年农民幸福观调查的实践感悟
2019/12/19 职场文书
MySQL触发器的使用
2021/05/24 MySQL
React列表栏及购物车组件使用详解
2021/06/28 Javascript