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与flash交互通信基础教程
Aug 07 Javascript
javascript 主动派发事件总结
Aug 09 Javascript
JQuery自适应窗口大小导航菜单附源码下载
Sep 01 Javascript
根据user-agent判断蜘蛛代码黑帽跳转代码(js版与php版本)
Sep 14 Javascript
JS简单限制textarea内输入字符数量的方法
Oct 14 Javascript
Node.js模块封装及使用方法
Mar 06 Javascript
微信小程序-图片、录音、音频播放、音乐播放、视频、文件代码实例
Nov 22 Javascript
Vue2实现组件props双向绑定
Dec 02 Javascript
JS实现AES加密并与PHP互通的方法分析
Apr 19 Javascript
vue-cli项目优化方法- 缩短首屏加载时间
Apr 01 Javascript
js实现每日签到功能
Nov 29 Javascript
jquery实现的分页显示功能示例
Aug 23 jQuery
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
基于mysql的论坛(3)
2006/10/09 PHP
php中的一个中文字符串截取函数
2007/02/14 PHP
PHP函数实现分页含文本分页和数字分页
2014/10/23 PHP
PHP实现双链表删除与插入节点的方法示例
2017/11/11 PHP
Nigma vs Liquid BO3 第二场2.14
2021/03/10 DOTA
JavaScript 利用Cookie记录用户登录信息
2009/12/08 Javascript
JavaScript 面向对象编程(1) 基础
2010/05/18 Javascript
jqPlot 基于jquery的画图插件
2011/04/26 Javascript
一个背景云变换js特效 鼠标移动背景云变化
2012/12/28 Javascript
JS实现悬浮移动窗口(悬浮广告)的特效
2013/03/12 Javascript
javascript中验证大写字母、数字和中文
2014/01/15 Javascript
JavaScript跨域方法汇总
2014/10/16 Javascript
jQuery on()绑定动态元素出现的问题小结
2016/02/19 Javascript
初步使用Node连接Mysql数据库
2016/03/03 Javascript
JavaScript实现两个select下拉框选项左移右移
2017/03/09 Javascript
Angular多选、全选、批量选择操作实例代码
2017/03/10 Javascript
关于react中组件通信的几种方式详解
2017/12/10 Javascript
详解mpvue scroll-view自动回弹bug解决方案
2018/10/01 Javascript
JS实现随机生成10个手机号的方法示例
2018/12/07 Javascript
openlayers4.6.5实现距离量测和面积量测
2020/09/25 Javascript
[05:17]DOTA2睡衣妹卖萌求签名 CJ第二天全明星影像
2013/07/28 DOTA
[04:12]第二届DOTA2亚洲邀请赛选手传记-Newbee.Sccc
2017/04/03 DOTA
python列表删除和多重循环退出原理详解
2020/03/26 Python
Python第三方包之DingDingBot钉钉机器人
2020/04/09 Python
Python 通过正则表达式快速获取电影的下载地址
2020/08/17 Python
python 实现百度网盘非会员上传超过500个文件的方法
2021/01/07 Python
澳大利亚领先的武术用品和健身器材供应商:SMAI
2019/03/24 全球购物
党校培训思想汇报
2013/12/30 职场文书
销售员岗位职责范本
2014/02/03 职场文书
自动一体化专业求职信
2014/03/15 职场文书
铁路安全事故反思
2014/04/26 职场文书
大学生党员自我剖析材料
2014/10/06 职场文书
小学生作文写作技巧100例,非常实用!
2019/07/08 职场文书
pytest配置文件pytest.ini的详细使用
2021/04/17 Python
利用Apache Common将java对象池化的问题
2022/06/16 Servers
SpringCloud超详细讲解Feign声明式服务调用
2022/06/21 Java/Android