Javascript 闭包与变量
1.闭包与变量
JavaScript中的作用域链的机制引出了一个副作用,即闭包只能取得包含函数中任何变量的最后一个值。闭包所保存的是整个变量对象,而不是某个特殊的值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
function createFunctions(){ var result= new Array(); for ( var i=0;i<10;i++){ result[i]= function (){ return i; }; } return result; } var funcs = createFunctions(); for ( var i=0; i < funcs.length; i++){ document.write(funcs[i]() + "<br />" ); } |
createFunction()函数返回一个数组。表面上看,似乎每个函数都应该返回自己的索引值,但事实并非如此,事实上每个函数的返回值都是10.因为每个函数的作用域链中都包含着createFunctions()函数的活动对象,所以它们引用的都是同一个变量i。当createFunctions()函数返回后,变量i的值就是10,此时每个函数都引用着保存变量i的同一个变量对象,所以每个函数返回后都是10.
当然我们可以使用匿名函数强制使闭包的行为符合预期。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
function createFunctions(){ var result= new Array(); for ( var i=0;i<10;i++){ result[i]= function (num){ return function (){ return num; }; }(i); } return result; } var funcs = createFunctions(); for ( var i=0; i < funcs.length; i++){ document.write(funcs[i]() + "<br />" ); } |
在重写了前面的createFunctions()函数后,每个函数就好返回各自不同的索引值了。在这里,我们没有直接把闭包赋值给数值,而是定义了一个匿名函数,并将立即执行该函数的结果赋值给数组。这里的匿名函数有一个参数num,也就是最终的函数要返回的值。在调用每个匿名函数时,我们传入了变量i。由于函数参数按值传递的,所以就会将变量i的当前值复制给参数num。而在这个匿名函数内部,有创建并返回了一个访问num的闭包。这样依赖,result数组中的每个函数都有自己num变量的一个副本,因此就可以返回各自不同的数值了。
1.2关于this对象
在闭包中使用this对象会出现一些问题,this对象是运行时基于函数的执行环境绑定的:在全局函数中,this等于window,而当函数被当作某个对象的方法调用时,this等于那个对象。不过,匿名函数的执行环境具有全局性,因此其this对象通常指向window(当然,在通过call()和apply()改变函数执行环境时,this指向其他对象)。
1
2
3
4
5
6
7
8
9
10
11
|
var name= "The Window" ; var object={ name: "My object" , getNameFunc: function (){ return function (){ return this .name; }; } }; alert(object.getNameFunc()()); //"The Window"(在非严格模式下) |
以上代码创建了一个全局变量name,有创建了一个包含那么属性的对象,这个对象还包括一个方法——getNameFunc(),它返回一个匿名函数,而匿名函数又返回this.name.由于getNameFunc()返会一个函数。因此调用object.getNameFunc()()就会立即返回调用它的函数,结果就返回一个字符串。然而,这个例子返回的字符串是“The Window”,即全局name变量的值。
但是,为什么匿名函数没有取得其包含作用域(或外部作用域)的this对象呢?
每个函数在调用时,其活动对象都会自动获取两个特殊的变量:this和arguments。内部函数在搜索这两个变量时,只会搜到其活动对象为止,因此永远不肯能访问到外部函数中的这两个变量。不过,把外部作用域中的this对象保存在一个闭包能够访问的变量里,就可以放闭包访问该对象了。
1
2
3
4
5
6
7
8
9
10
11
12
|
var name= "The Window" ; var object={ name: "My object" , getNameFunc: function (){ var that= this ; return function (){ return that.name; }; } }; alert(object.getNameFunc()()); //"My object" |
以上代码中,我们在定义匿名函数之前,把this对象赋值给了that变量,而在定义闭包之后,闭包也可以访问这个变量,因为它们是我们在外部函数中特意声明的一个变量。即使在函数返回之后,this也仍然引用的object,所以调用object.getName()()就返回“My object”.
Javascript 闭包与变量的更多相关文章
- JavaScript闭包与变量的经典问题
许多人第一次接触闭包大概都是从高程里这段代码开始的: function createFunctions() { var result = new Array(); for(var i=0; i< ...
- 那些年,我们误解的 JavaScript 闭包
说到闭包,大部分的初始者,都是谈虎色变的.最近对闭包,有了自己的理解,就感觉.其实我们误解闭包.也被网上各种说的闭包的解释给搞迷糊. 一句话:要想理解一个东西还是看权威的东西. 下面我来通俗的讲解一个 ...
- JavaScript 使用闭包防止变量污染
javaScript在多人协作时,如果定义过多的全局变量 有可能造成全局变量命名冲突,使用闭包来解决功能对变量的调用 将变量写到一个独立的空间里面 就是闭包里面 var name = "外部 ...
- JavaScript 使用闭包保护变量 防止污染
使用JavaScript编写插件或团队协作时,可使用闭包来解决此类以下两个问题: 1.定义过多全局变量,可能会造成全局变量命名冲突: 2.在插件内定义变量,需要保护该变量不被轻易修改: 优点:可以把局 ...
- 《Web 前端面试指南》1、JavaScript 闭包深入浅出
闭包是什么? 闭包是内部函数可以访问外部函数的变量.它可以访问三个作用域:首先可以访问自己的作用域(也就是定义在大括号内的变量),它也能访问外部函数的变量,和它能访问全局变量. 内部函数不仅可以访问外 ...
- JavaScript 闭包深入浅出
闭包是什么? 闭包是内部函数可以访问外部函数的变量.它可以访问三个作用域:首先可以访问自己的作用域(也就是定义在大括号内的变量),它也能访问外部函数的变量,和它能访问全局变量. 内部函数不仅可以访问外 ...
- JavaScript闭包(Closure)
JavaScript闭包(Closure) 本文收集了多本书里对JavaScript闭包(Closure)的解释,或许会对理解闭包有一定帮助. <你不知道的JavsScript> Java ...
- JavaScript闭包浅谈
------------------- 作者:willingtolove: 本文链接:http://www.cnblogs.com/willingtolove/p/4745889.html 1. 变量 ...
- 学习JavaScript闭包
作者: 阮一峰 日期: 2009年8月30日 闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 下面就是我的学习笔记,对于Javascript初 ...
随机推荐
- 使用OpenCV玩家营造出一个视频控制(没有声音)
说明:OpenCV计算机视觉库,所以使用的图像或视频处理,因此,没有任何声音在播放视频的临时 软件:使用OpenCV制播放器(无声音) 功能说明:新建播放窗体.加入进度条能够拖动视频播放. 流程图: ...
- js 拖拽实现
代码参考 <!DOCTYPE html> <html lang="en"> <title>拖拽</title> <head&g ...
- 使用.net备份和还原数据库
原文:使用.net备份和还原数据库 CSDN网友的提问http://community.csdn.net/Expert/TopicView3.asp?id=4929678C#实现SQLSERVER20 ...
- 使用UDL文件来测试SQL Server数据库连接
原文 来自http://www.2cto.com/database/201308/234427.html 使用UDL测试SQL Server连接问题 做数据库经常会遇到SQL Server连接的问 ...
- javascript 函数介绍
javascript函数使用的时候,往往都比较单一,这里介绍几种不同于我们之前使用的函数调用方式! 1.函数表达式包含名称,用于递归 var f = function s(num) { if (num ...
- having在Oracle和mysql小点不同
在Oracle中,having一定要结合group by使用,但在mysql中,情况就不一样了.能够单独使用. C:\Documents and Settings\guogang>sqlplus ...
- leetcode[164] Maximum Gap
梅西刚梅开二度,我也记一题. 在一个没排序的数组里,找出排序后的相邻数字的最大差值. 要求用线性时间和空间. 如果用nlgn的话,直接排序然后判断就可以了.so easy class Solution ...
- Solr多核心及分词器(IK)配置
Solr多核心及分词器(IK)配置 多核心的概念 多核心说白了就是多索引库.也可以理解为多个"数据库表" 说一下使用multicore的真实场景,比若说,产品搜索和会员信息搜索 ...
- 在C#中Color结构的各属性颜色对照表(转)
转自:http://blog.sina.com.cn/s/blog_454dc49501016q2p.html Color.AliceBlue 240,248,255 Color.LightSalmo ...
- px/em/pt区别和转换
老是被人问到px.pt和em的区别,自己有时候也会纠结到底该用什么单位,今天特意查了一些文章,下面这篇虽然很久远了,但解释的比较全面,转载收藏之.点击查看原文 这里引用的是Jorux的“95%的中国网 ...