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使用过程中需要注意的地方和一些基本语法
Aug 26 Javascript
2010年最佳jQuery插件整理
Dec 06 Javascript
setTimeout的延时为0时多个浏览器的区别
May 23 Javascript
分享Javascript中最常用的55个经典小技巧
Nov 29 Javascript
js css 实现遮罩层覆盖其他页面元素附图
Sep 22 Javascript
对JavaScript的全文搜索实现相关度评分的功能的方法
Jun 24 Javascript
基于jQuery和CSS3制作响应式水平时间轴附源码下载
Dec 20 Javascript
jQuery点击输入框显示验证码图片
May 19 Javascript
JavaScript数据类型转换的注意事项
Jul 31 Javascript
前端开发不得不知的10个最佳ES6特性
Aug 30 Javascript
微信小程序云开发之模拟后台增删改查
May 16 Javascript
Vue提供的三种调试方式你知道吗
Jan 18 Vue.js
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中3种生成XML文件方法的速度效率比较
2012/10/06 PHP
PHP把小数转成整数3种方法
2014/06/30 PHP
PHP获取数组最后一个值的2种方法
2015/01/21 PHP
浅谈json_encode用法
2015/03/05 PHP
PHP SPL标准库中的常用函数介绍
2015/05/11 PHP
调试WordPress中定时任务的相关PHP脚本示例
2015/12/10 PHP
PHP下使用mysqli的函数连接mysql出现warning: mysqli::real_connect(): (hy000/1040): ...
2016/02/14 PHP
Zend Framework实现Zend_View集成Smarty模板系统的方法
2016/03/05 PHP
PHP中register_shutdown_function函数的基础介绍与用法详解
2017/11/28 PHP
修改好的jquery滚动字幕效果实现代码
2011/06/22 Javascript
javascript中获取下个月一号,是星期几
2012/06/01 Javascript
深入理解JavaScript系列(36):设计模式之中介者模式详解
2015/03/04 Javascript
Bootstrap 组件之按钮(二)
2016/05/11 Javascript
node.js 抓取代理ip实例代码
2017/04/30 Javascript
angular.js指令中的controller、compile与link函数的不同之处
2017/05/10 Javascript
angular学习之从零搭建一个angular4.0项目
2017/07/10 Javascript
Vue2.0设置全局样式(less/sass和css)
2017/11/18 Javascript
解决vue中post方式提交数据后台无法接收的问题
2018/08/11 Javascript
layui插件表单验证提交触发提交的例子
2019/09/09 Javascript
JQuery 实现文件下载的常用方法分析
2019/10/29 jQuery
JavaScript ECMA-262-3 深入解析(一):执行上下文实例分析
2020/04/25 Javascript
vue缓存之keep-alive的理解和应用详解
2020/11/02 Javascript
[11:27]《一刀刀一天》之DOTA全时刻20:TI4总奖金突破920W TS赛事分析
2014/06/18 DOTA
[01:02:04]EG vs Liquid 2019国际邀请赛淘汰赛 败者组 BO3 第一场 8.23
2019/09/05 DOTA
Python实现微信公众平台自定义菜单实例
2015/03/20 Python
为Python程序添加图形化界面的教程
2015/04/29 Python
python使用Image处理图片常用技巧分析
2015/06/01 Python
在Django的URLconf中进行函数导入的方法
2015/07/18 Python
python 检查文件mime类型的方法
2018/12/08 Python
ipython和python区别详解
2019/06/26 Python
详解scrapy内置中间件的顺序
2020/09/28 Python
校园摄影活动策划方案
2014/02/05 职场文书
2015年八一建军节慰问信
2015/03/23 职场文书
幼儿园校车安全责任书
2015/05/08 职场文书
AJAX学习笔记
2021/05/18 Javascript
如何有效防止sql注入的方法
2021/05/25 SQL Server