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 相关文章推荐
ajax 缓存 问题 requestheader
Aug 01 Javascript
JS弹出层的显示与隐藏示例代码
Dec 27 Javascript
jQuery窗口、文档、网页各种高度的精确理解
Jul 02 Javascript
基于jquery编写的放大镜插件
Mar 23 Javascript
jQuery 获取跨域XML(RSS)数据的相关总结分析
May 18 Javascript
JavaScript原型继承_动力节点Java学院整理
Jun 30 Javascript
简述Angular 5 快速入门
Nov 04 Javascript
详解layui中的树形关于取值传值问题
Jan 16 Javascript
JavaScript笛卡尔积超简单实现算法示例
Jul 30 Javascript
使用canvas实现一个vue弹幕组件功能
Nov 30 Javascript
javascript实现简单打字游戏
Oct 29 Javascript
nuxt 页面路由配置,主页轮播组件开发操作
Nov 05 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 类自动载入的方法
2015/06/03 PHP
php生成过去100年下拉列表的方法
2015/07/20 PHP
php之static静态属性与静态方法实例分析
2015/07/30 PHP
PHP基于curl后台远程登录正方教务系统的方法
2016/10/14 PHP
php利用云片网实现短信验证码功能的示例代码
2017/11/18 PHP
Laravel关系模型指定条件查询方法
2019/10/10 PHP
PHP实现页面静态化深入讲解
2021/03/04 PHP
统计出现最多的字符次数的js代码
2010/12/03 Javascript
13 款最热门的 jQuery 图像 360 度旋转插件推荐
2014/12/09 Javascript
jQuery中delegate()方法用法实例
2015/01/19 Javascript
javascript中函数作为参数调用的方法
2015/02/09 Javascript
关于session和cookie的简单理解
2016/06/08 Javascript
ES6新特性之Symbol类型用法分析
2017/03/31 Javascript
深入理解ES6之数据解构的用法
2018/01/13 Javascript
基于百度地图api清除指定覆盖物(Overlay)的方法
2018/01/26 Javascript
webpack项目轻松混用css module的方法
2018/06/12 Javascript
初学Python函数的笔记整理
2015/04/07 Python
Python中用于去除空格的三个函数的使用小结
2015/04/07 Python
深入理解 Python 中的多线程 新手必看
2016/11/20 Python
Django ORM框架的定时任务如何使用详解
2017/10/19 Python
python 拷贝特定后缀名文件,并保留原始目录结构的实例
2018/04/27 Python
Django开发中的日志输出的方法
2018/07/02 Python
python读取几个G的csv文件方法
2019/01/07 Python
CentOS7安装Python3的教程详解
2019/04/10 Python
简单了解Python matplotlib线的属性
2019/06/29 Python
python 设置输出图像的像素大小方法
2019/07/04 Python
解决python虚拟环境切换无效的问题
2020/04/30 Python
pandas处理csv文件的方法步骤
2020/10/16 Python
国际象棋商店:The Chess Store
2018/07/09 全球购物
UNIX命令速查表
2012/03/10 面试题
自动化专业职业生涯规划书范文
2014/01/16 职场文书
婚礼秀策划方案
2014/05/19 职场文书
质量月口号
2014/06/20 职场文书
2015大学自主招生自荐信范文
2015/03/04 职场文书
拉贝日记观后感
2015/06/05 职场文书
创业计划书之青年旅馆
2019/09/23 职场文书