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 相关文章推荐
Jquery实现仿新浪微博获取文本框能输入的字数代码
Feb 22 Javascript
用Jquery.load载入页面实现局部刷新
Jan 22 Javascript
JavaScript返回0-1之间随机数的方法
Apr 06 Javascript
js基于cookie方式记住返回页面用法示例
May 27 Javascript
jQuery Ajax Post 回调函数不执行问题的解决方法
Aug 15 Javascript
js正则表达式惰性匹配和贪婪匹配用法分析
Dec 26 Javascript
ES6新数据结构Map功能与用法示例
Mar 31 Javascript
Vue在页面数据渲染完成之后的调用方法
Sep 11 Javascript
微信小程序实现底部导航
Nov 05 Javascript
微信小程序设置全局请求URL及封装wx.request请求操作示例
Apr 02 Javascript
vue-video-player 解决微信自动全屏播放问题(横竖屏导致样式错乱问题)
Feb 25 Javascript
使用vuex-persistedstate本地存储vuex
Apr 29 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
《雄兵连》系列首部大电影《烈阳天道》:可能是因为期望值太高了
2020/08/18 国漫
php实现向javascript传递数组的方法
2015/07/27 PHP
Zend Framework生成验证码并实现验证码验证功能(附demo源码下载)
2016/03/22 PHP
在IE中调用javascript打开Excel的代码(downmoon原作)
2007/04/02 Javascript
javascript学习之闭包分析
2010/12/02 Javascript
利用CSS、JavaScript及Ajax实现高效的图片预加载
2013/10/16 Javascript
javascript中substring()、substr()、slice()的区别
2015/08/30 Javascript
Javascript之BOM(window对象)详解
2016/05/25 Javascript
全面了解JavaScirpt 的垃圾(garbage collection)回收机制
2016/07/11 Javascript
DOM中事件处理概览与原理的全面解析
2016/08/16 Javascript
Bootstrap源码解读导航条(7)
2016/12/23 Javascript
angular ng-repeat数组中的数组实例
2017/02/18 Javascript
关于vue.js过渡css类名的理解(推荐)
2017/04/10 Javascript
Vue.js使用$.ajax和vue-resource实现OAuth的注册、登录、注销和API调用
2017/05/10 Javascript
如何把vuejs打包出来的文件整合到springboot里
2018/07/26 Javascript
详解JSON Web Token 入门教程
2018/07/30 Javascript
简单说说angular.json文件的使用
2018/10/29 Javascript
vue计算属性computed、事件、监听器watch的使用讲解
2019/01/21 Javascript
ES6知识点整理之函数对象参数默认值及其解构应用示例
2019/04/17 Javascript
如何在JavaScript中创建具有多个空格的字符串?
2020/02/23 Javascript
vue用elementui写form表单时,在label里添加空格操作
2020/08/13 Javascript
[02:25]DOTA2英雄基础教程 虚空假面
2014/01/02 DOTA
python中input()与raw_input()的区别分析
2016/02/27 Python
Python使用修饰器进行异常日志记录操作示例
2019/03/19 Python
解决Tensorflow 内存泄露问题
2020/02/05 Python
去除python中的字符串空格的简单方法
2020/12/22 Python
Watch Station官方网站:世界一流的手表和智能手表
2020/01/05 全球购物
护士自我鉴定怎么写
2014/02/07 职场文书
劳动竞赛活动方案
2014/02/20 职场文书
2015法院个人工作总结范文
2015/05/25 职场文书
鸦片战争观后感
2015/06/09 职场文书
2016年教师学习廉政准则心得体会
2016/01/20 职场文书
汉语拼音教学反思
2016/02/22 职场文书
能让Python提速超40倍的神器Cython详解
2021/06/24 Python
Redis+AOP+自定义注解实现限流
2022/06/28 Redis
HTML中link标签属性的具体用法
2023/05/07 HTML / CSS