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 append() html时的小问题的解决方法
Dec 16 Javascript
基于JavaScript实现继承机制之原型链(prototype chaining)的详解
May 07 Javascript
JavaScript插件化开发教程 (一)
Jan 27 Javascript
jquery动态添加删除(tr/td)
Feb 09 Javascript
JavaScript分页功能的实现方法
Apr 25 Javascript
JS中的hasOwnProperty()和isPrototypeOf()属性实例详解
Aug 11 Javascript
jQuery中select与datalist制作下拉菜单时的区别浅析
Dec 30 Javascript
从零开始做一个pagination分页组件
Mar 15 Javascript
利用adb shell和node.js实现抖音自动抢红包功能(推荐)
Feb 22 Javascript
微信小程序手机号码验证功能的实例代码
Aug 28 Javascript
vue中的watch监听数据变化及watch中各属性的详解
Sep 11 Javascript
Vue3实现简易音乐播放器组件
Aug 14 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面向对象全攻略 (五) 封装性
2009/09/30 PHP
PHP得到mssql的存储过程的输出参数功能实现
2012/11/23 PHP
PHP应用JSON技巧讲解
2013/02/03 PHP
PHP_NETWORK_GETADDRESSES: GETADDRINFO FAILED问题解决办法
2014/05/04 PHP
php数组冒泡排序算法实例
2016/05/06 PHP
PHP实现绘制二叉树图形显示功能详解【包括二叉搜索树、平衡树及红黑树】
2017/11/16 PHP
PHP+Redis 消息队列 实现高并发下注册人数统计的实例
2018/01/29 PHP
PHP获取对象属性的三种方法实例分析
2019/01/03 PHP
Display SQL Server Login Mode
2007/06/21 Javascript
基于jquery的无限级联下拉框js插件
2011/10/29 Javascript
javascript获取浏览器类型和版本的方法(js获取浏览器版本)
2014/03/13 Javascript
[将免费进行到底]在Amazon的一年免费服务器上安装Node.JS, NPM和OurJS博客
2014/08/18 Javascript
js生成随机数的方法实例
2015/10/16 Javascript
基于JavaScript实现简单的随机抽奖小程序
2016/01/05 Javascript
浅谈Cookie的生命周期问题
2016/08/02 Javascript
原生JS实现轮播效果+学前端的感受(防止走火入魔)
2016/08/21 Javascript
nodejs body-parser 解析post数据实例
2017/07/26 NodeJs
jQuery初级教程之网站品牌列表效果
2017/08/02 jQuery
原生js实现密码强度验证功能
2020/03/18 Javascript
JS数组push、unshift、pop、shift方法的实现与使用方法示例
2020/04/29 Javascript
JavaScript 面向对象程序设计详解【类的创建、实例对象、构造函数、原型等】
2020/05/12 Javascript
利用python写个下载teahour音频的小脚本
2017/05/08 Python
selenium+python设置爬虫代理IP的方法
2018/11/29 Python
python+opencv实现霍夫变换检测直线
2020/10/23 Python
Python基础学习之时间转换函数用法详解
2019/06/18 Python
Tensorflow与Keras自适应使用显存方式
2020/06/22 Python
Python调用C/C++的方法解析
2020/08/05 Python
python语言实现贪吃蛇游戏
2020/11/13 Python
python3中calendar返回某一时间点实例讲解
2020/11/18 Python
为奢侈时尚带来了慈善元素:Olivela
2018/09/29 全球购物
IBatis持久层技术
2016/07/18 面试题
学校运动会开幕演讲稿
2014/01/04 职场文书
旅游网创业计划书
2014/01/31 职场文书
会计专业自荐信
2014/06/03 职场文书
助学贷款贫困证明
2014/09/23 职场文书
党员群众路线自我剖析材料
2014/10/06 职场文书