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自带函数备忘 数组
Dec 29 Javascript
JS event使用方法详解
Apr 28 Javascript
深入理解JavaScript作用域和作用域链
Oct 21 Javascript
处理及遍历XML文档DOM元素属性及方法整理
Aug 23 Javascript
Javascript 多浏览器兼容总结(实战经验)
Oct 30 Javascript
JS连接SQL数据库与ACCESS数据库的方法实例
Nov 21 Javascript
JS方法调用括号的问题探讨
Jan 24 Javascript
jquery validate和jquery form 插件组合实现验证表单后AJAX提交
Aug 26 Javascript
AngularJS实现分页显示数据库信息
Jul 01 Javascript
BootStrap中
Dec 10 Javascript
详解Vue webapp项目通过HBulider打包原生APP
Jun 29 Javascript
详解JS浏览器事件循环机制
Mar 27 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中使用Imagick实现图像直方图的实现代码
2011/08/30 PHP
destoon实现公司新闻详细页添加评论功能的方法
2014/07/15 PHP
php+mysql大量用户登录解决方案分析
2014/12/29 PHP
PHP CURL 内存泄露问题解决方法
2015/02/12 PHP
php实现专业获取网站SEO信息类实例
2015/04/02 PHP
php curl上传、下载、https登陆实现代码
2017/07/23 PHP
php实现的简单多进程服务器类完整示例
2020/02/01 PHP
jquery遍历input取得input的name
2009/04/27 Javascript
JavaScript判断用户名和密码不能为空的实现代码
2016/05/16 Javascript
AngularJS 单元测试(二)详解
2016/09/21 Javascript
用React实现一个完整的TodoList的示例代码
2017/10/30 Javascript
vue.js使用watch监听路由变化的方法
2018/07/08 Javascript
深入了解JavaScript代码覆盖
2019/06/13 Javascript
Vue中点击active并第一个默认选中功能的实现
2020/02/24 Javascript
Python编程中的for循环语句学习教程
2015/10/14 Python
Python实现的简单模板引擎功能示例
2017/09/02 Python
python 3.6 +pyMysql 操作mysql数据库(实例讲解)
2017/12/20 Python
详解python字节码
2018/02/07 Python
1分钟快速生成用于网页内容提取的xslt
2018/02/23 Python
将string类型的数据类型转换为spark rdd时报错的解决方法
2019/02/18 Python
python pygame实现滚动横版射击游戏城市之战
2019/11/25 Python
Python 将 QQ 好友头像生成祝福语的实现代码
2020/05/03 Python
PyQt5-QDateEdit的简单使用操作
2020/07/12 Python
如何在Canvas中添加事件的方法示例
2019/05/21 HTML / CSS
英国领先的野生鸟类食品供应商:GardenBird
2018/08/09 全球购物
Piercing Pagoda官网:耳环、戒指、项链、手链等
2020/09/28 全球购物
新西兰最大的连锁超市:Countdown
2020/06/04 全球购物
草船借箭教学反思
2014/02/03 职场文书
演讲稿格式
2014/04/30 职场文书
学校地质灾害防治方案
2014/06/10 职场文书
酒店周年庆活动方案
2014/08/21 职场文书
担保书范本
2015/01/20 职场文书
2016自主招生校长推荐信范文
2015/03/23 职场文书
预备党员考察意见范文
2015/06/01 职场文书
婚前协议书怎么写,才具有法律效力呢 ?
2019/06/28 职场文书
PHP使用非对称加密算法RSA
2021/04/21 PHP