JavaScript闭包函数访问外部变量的方法
2014-08-27 00:00
891 查看
闭包是指有权访问另一个函数作用域中的变量的函数,但作用域的配置机制有一个需要注意的地方,即闭包只能取得包含函数中任何变量的最后一个值。
如以下案例:
执行结果:
表面上看,似乎每个函数返回的i值都不相同,比如c_arr[0]的值应该是0,c_arr[1]的值应该是1,以此类推。可结果每个函数都返回10。为什么呢?
因为每个函数的作用域链中保存着create()函数的活动对象,所以它们引用的都是同一个变量i。当for循环结束以后,i的值也就变成10了,此时每个函数都引用保存变量i的同一个变量对象。
我们可以通过创建另一个域名函数强制让闭包的行为符合预期,使每个位置对应相应的值。
执行结果:
定义了一个匿名函数,并立即执行匿名函数的机过赋给数组,这里匿名函数有一个参数num,也就是最终的函数要返回的值。在调用每个函数时我们传入变量i。由于函数参数是按值传递的,所以就会将变量i的当前值赋值给参数num。而在这个匿名函数内部,又创建并返回了一个访问num的闭包,这样一来arr数组中的每个函数都有自己num变量的一个副本,因此就可以返回各自不同的数值了。
经典例子
我们再来看一个经典的例子,假设页面有一组button标签,我们利用脚本给这组button标签绑定单击事件,并且单击时能弹出这是第几个标签。
点击每一个按钮结果
表面上看,似乎单击每一个标签应该弹出不同数字
第一个应该弹出0;
第二个应该弹出1;
以此类推。
可结果是所有按钮都弹出4,显然这不是我们想要的结果。
我们把程序改一下
点击第二个
点击第四个
我们只需要在函数内建立一个匿名函数,同以上案例同理。即可实现匿名函数捕获外部变量i,结果每个按钮弹的i值都不同。
如以下案例:
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 />"); }
执行结果:
表面上看,似乎每个函数返回的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 />"); }
执行结果:
定义了一个匿名函数,并立即执行匿名函数的机过赋给数组,这里匿名函数有一个参数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>
点击每一个按钮结果
表面上看,似乎单击每一个标签应该弹出不同数字
第一个应该弹出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>
点击第二个
点击第四个
我们只需要在函数内建立一个匿名函数,同以上案例同理。即可实现匿名函数捕获外部变量i,结果每个按钮弹的i值都不同。
相关文章推荐
- JavaScript闭包函数访问外部变量的方法
- Java基础之static域访问外部变量和方法
- Flash as3.0 中 mc 访问父级 root 函数,变量等的方法
- 类中内部类中的方法访问外部类中变量的示例
- 为什么不管是静态内部类的普通方法还是静态方法都不能访问外部类的实例变量
- 匿名内部类不能访问外部类方法中的局部变量,除非变量被声明为final类型
- javascript与cs代码互相调用 asp.net中前台javascript与后台C#交互 这里主要包括了javascipt与后台CS代码四种方法互调(其中包括函数与变量的访问)
- Angular外部使用js调用Angular控制器中的函数方法或变量用法示例
- [ActionScript 3.0] flash如何访问父级或者舞台上的变量、函数等的方法
- JAVA匿名内部类不能访问外部类方法中的局部变量,除非变量被声明为final类型
- Java类的嵌套:外部类的方法不能访问内部类的变量
- python嵌套函数使用外部函数变量的方法(Python2和Python3)
- 定义一个包含私有成员变量和函数的类,再定义一个内部类,在内部类函数中访问外部成员变量,并调用外部函数。在外部类函数中创建内部类对象,调用内部类函数
- 内部类访问外部类的变量必须是final吗,java静态方法中不能引用非静态变量,静态方法中不能创建内部类的实例
- vbscript访问函数外类变量和全局变量的方法
- js使用闭包时,内部函数是直接访问外部函数的实际变量而非复制一份新变量
- Java基础之static域访问外部变量和方法
- ros(robot operating system机器人操作系统)订阅函数的多线程使用方法(C++: 外部变量控制跳出for循环)
- 在Angular外部使用js调用Angular控制器中提供的函数方法或变量
- itemRender---之outerDocument : 使用itemRender 和item Editor时想要访问外部变量或方法的关键字