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和Java获取各种form表单信息的简单实例
Feb 14 Javascript
JavaScript实现仿网易通行证表单验证
May 25 Javascript
使用AmplifyJS组件配合JavaScript进行编程的指南
Jul 28 Javascript
jQuery 判断图片是否加载完成方法汇总
Aug 10 Javascript
谈谈JSON对象和字符串之间的相互转换JSON.stringify(obj)和JSON.parse(string)
Oct 01 Javascript
JS简单测试循环运行时间的方法
Sep 04 Javascript
vuejs通过filterBy、orderBy实现搜索筛选、降序排序数据
Oct 26 Javascript
JavaScript轮播图简单制作方法
Feb 20 Javascript
基于vue中keep-alive缓存问题的解决方法
Sep 21 Javascript
详解Vue SSR( Vue2 + Koa2 + Webpack4)配置指南
Nov 13 Javascript
深入理解vue-class-component源码阅读
Feb 18 Javascript
Vue实现类似Spring官网图片滑动效果方法
Mar 01 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 PDOStatement对象bindpram()、bindvalue()和bindcolumn之间的区别
2014/11/20 PHP
浅析PHP 中move_uploaded_file 上传中文文件名失败
2019/04/17 PHP
HTML IMG标签 onload 内存溢出导致浏览器CPU占用过高
2021/03/09 Javascript
JScript 脚本实现文件下载 一般用于下载木马
2009/10/29 Javascript
JS常见问题整理(持续更新)
2013/08/06 Javascript
javascript的propertyIsEnumerable()方法使用介绍
2014/04/09 Javascript
jQuery中DOM树操作之复制元素的方法
2015/01/23 Javascript
js库Modernizr的介绍和使用
2015/05/07 Javascript
JavaScript实现快速排序的方法
2015/07/31 Javascript
Vue.js每天必学之组件与组件间的通信
2016/09/08 Javascript
JavaScript九九乘法口诀表的简单实现
2016/10/04 Javascript
vue.js使用代理和使用Nginx来解决跨域的问题
2018/02/03 Javascript
详解微信小程序之一键复制到剪切板
2019/04/24 Javascript
nodejs制作小爬虫功能示例
2020/02/24 NodeJs
python进程管理工具supervisor使用实例
2014/09/17 Python
Python构造函数及解构函数介绍
2015/02/26 Python
详解在Python的Django框架中创建模板库的方法
2015/07/20 Python
利用numpy+matplotlib绘图的基本操作教程
2017/05/03 Python
python编写分类决策树的代码
2017/12/21 Python
Django 简单实现分页与搜索功能的示例代码
2019/11/07 Python
pycharm中导入模块错误时提示Try to run this command from the system terminal
2020/03/26 Python
Evisu官方网站:日本牛仔品牌,时尚街头设计风格
2016/12/30 全球购物
澳大利亚排名第一的儿童在线玩具商店:Toy Galaxy
2018/10/06 全球购物
澳大利亚在线家具、灯饰和家居装饰店:LivingStyles
2018/11/20 全球购物
美国最大的购物网站:Amazon.com(亚马逊美国)
2020/05/23 全球购物
瑞典最大的儿童用品网上商店:pinkorblue.se
2021/03/09 全球购物
用C或者C++语言实现SOCKET通信
2015/02/24 面试题
商场总经理岗位职责
2014/02/03 职场文书
自我查摆剖析材料
2014/10/11 职场文书
三年级上册科学教学计划
2015/01/21 职场文书
2015年采购员工作总结
2015/04/27 职场文书
学困生转化工作总结
2015/08/13 职场文书
中考百日冲刺决心书
2015/09/22 职场文书
2016春季运动会前导词
2015/11/25 职场文书
CSS3 制作的彩虹按钮样式
2021/04/11 HTML / CSS
html中显示特殊符号(附带特殊字符对应表)
2021/06/21 HTML / CSS