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 动态修改样式和层叠样式表代码
Apr 27 Javascript
用JS实现一个TreeMenu效果分享
Aug 28 Javascript
两种常用的javascript数组去重方法思路及代码
Mar 26 Javascript
jquery 获取表单元素里面的值示例代码
Jul 28 Javascript
javascript自定义右键弹出菜单实现方法
May 25 Javascript
jQuery实现下滑菜单导航效果代码
Aug 25 Javascript
JS和jQuery通过this获取html标签中的属性值(实例代码)
Sep 11 jQuery
浅谈使用React.setState需要注意的三点
Dec 18 Javascript
Vue Socket.io源码解读
Feb 07 Javascript
react+ant design实现Table的增、删、改的示例代码
Dec 27 Javascript
在layui中使用form表单监听ajax异步验证注册的实例
Sep 03 Javascript
Vue和React有哪些区别
Sep 12 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+AJAX实现无刷新注册(带用户名实时检测)
2006/12/02 PHP
php判断上传的Excel文件中是否有图片及PHPExcel库认识
2013/01/11 PHP
CI框架安全类Security.php源码分析
2014/11/04 PHP
PHP中的命名空间相关概念浅析
2015/01/22 PHP
THINKPHP支持YAML配置文件的设置方法
2015/03/17 PHP
php 数组字符串搜索array_search技巧
2016/07/05 PHP
JavaScript中的私有成员
2006/09/18 Javascript
checkbox设置复选框的只读效果不让用户勾选
2013/08/12 Javascript
JS实现日期加减的方法
2013/11/29 Javascript
动态的创建一个元素createElement及删除一个元素
2014/01/24 Javascript
基于jquery实现的可编辑下拉框实现代码
2014/08/02 Javascript
D3.js 从P元素的创建开始(显示可加载数据)
2014/10/30 Javascript
在浏览器中打开或关闭JavaScript的方法
2015/06/03 Javascript
Bootstrap轮播加上css3动画,炫酷到底!
2015/12/22 Javascript
JS获取随机数和时间转换的简单实例
2016/07/10 Javascript
Angular2 环境配置详细介绍
2016/09/21 Javascript
jQuery用noConflict代替$的实现方法
2017/04/12 jQuery
js移动端事件基础及常用事件库详解
2017/08/15 Javascript
vuex中使用对象展开运算符的示例
2017/09/25 Javascript
在Vue mounted方法中使用data变量详解
2019/11/05 Javascript
使用Python从有道词典网页获取单词翻译
2016/07/03 Python
Python实现FLV视频拼接功能
2020/01/21 Python
Python 动态变量名定义与调用方法
2020/02/09 Python
Python实现子类调用父类的初始化实例
2020/03/12 Python
伦敦哈德森鞋:Hudson Shoes
2018/02/06 全球购物
财务会计人员求职的自我评价
2014/01/13 职场文书
医药个人求职信范文
2014/01/29 职场文书
30年同学聚会感言
2014/01/30 职场文书
物业保安员岗位职责
2014/03/14 职场文书
自强自立美德少年事迹材料
2014/08/16 职场文书
违反交通法规检讨书
2014/09/10 职场文书
党员群众路线教育实践活动学习笔记
2014/11/05 职场文书
十大经典日本动漫排行榜 海贼王第三,犬夜叉仅第八
2022/03/18 日漫
HTML5基础学习之文本标签控制
2022/03/25 HTML / CSS
Lakehouse数据湖并发控制陷阱分析
2022/03/31 Oracle
Python万能模板案例之matplotlib绘制直方图的基本配置
2022/04/13 Python