【JavaScript回顾】闭包
什么是闭包?
闭包是指有权访问另一个 函数作用域中的变量的函数(也就是说,你这个函数用到的变量另外一个域的就算闭包)
<script>
function f1() {
var age = 10; //这个函数就是闭包
function f2() {
return age;
}
return f2;
} alert(f1()()); </script>
在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
闭包与变量 (这里需要注意的)
function createFunctions() {
            var result = new Array();
            for (var i = 0; i < 10; i++) {
                result[i] = function () {
                    return i;
                };
            }
            return result;
        }
如上代码,如果调用以后所有的值都会是10,而不是我们预想的1-10,这是因为每个函数的作用域链中 都保存着 createFunctions()函数的活动对象,所以它们引用的都是同一个变量 i。当 createFunctions()函数返回后,变量 i 的值是 10,此时每个函数都引用着保存变量 i 的同一个变量 对象,所以在每个函数内部 i 的值都是 10。但是,我们可以通过创建另一个匿名函数强制让闭包的行为 符合预期,如下所示。
<script>
function createFunctions() {
var result = new Array();
for (var i = 0; i < 10; i++) {
result[i] = function (num) {
return function () {
return num;
}
}(i);//这里直接调用了闭包(function(num)这个函数),
//所以result存的是function(){return num;}这个函数
//当然,也可以直接调用,那么下面就不用写()了:createFunctions()[8]
}
return result;
} alert(createFunctions()[8]());
</script>
在重写了前面的 createFunctions()函数后,每个函数就会返回各自不同的索引值了。在这个版 本中,我们没有直接把闭包赋值给数组,而是定义了一个匿名函数,并将立即执行该匿名函数的结果赋 给数组。这里的匿名函数有一个参数 num,也就是终的函数要返回的值。在调用每个匿名函数时,我 们传入了变量 i。由于函数参数是按值传递的,所以就会将变量 i 的当前值复制给参数 num。而在这个 匿名函数内部,又创建并返回了一个访问 num 的闭包。这样一来,result 数组中的每个函数都有自己 num 变量的一个副本,因此就可以返回各自不同的数值了。
闭包中的this对象
我们知道,this 对象是在运行时基于函数的执 行环境绑定的:在全局函数中,this 等于 window,而当函数被作为某个对象的方法调用时,this 等于那个对象。不过,匿名函数的执行环境具有全局性,因此其 this 对象通常指向 window①。但有时候 由于编写闭包的方式不同,这一点可能不会那么明显。下面来看一个例子
<script>
var name = "Windows"; var obj = {
name: "closure",
getName: function () {
return function () {
return this.name;
}
}
}
alert(obj.getName()());
</script>
这个例子该死的正确的答案居然是:Windows, 搞了吧!!! Why?
每个函数在被调用时都会自动取得两个特殊变量:this 和 arguments。内部函数在搜索这两个变量时,只会搜索到其活动对象为止,因此永远不可能直接访问外部函数中的这两个变量。不过,把外部作用域中的 this 对象保存在一个闭包能够访问 到的变量里,就可以让闭包访问该对象了,如下所示
<script>
var name = "Windows"; var obj = {
name: "closure",
getName: function () {
var that = this;
return function () {
return that.name;
}
}
}
alert(obj.getName()());
</script>
在定义匿名函数之前,我们把 this 对象赋值给了一个名叫 that 的变量。而在定义了闭包之后,闭包也可以访问这个变量,因为它是我们 在包含函数中特意声名的一个变量。即使在函数返回之后,that 也仍然引用着 object,所以调用 object.getNameFunc()()就返回了"My Object"。
来看下三种不同的调用getName的方式的不同结果:
alert(object.getName());
alert((object.getName)());
alert((object.getName = object.getName)());
返回值:1.closure
2.closure
3.Windows
第一行代码跟平常一样调用了 object.getName(),返回的是"closure",因为 this.name 就是 object.name。第二行代码在调用这个方法前先给它加上了括号。虽然加上括号之后,就好像只 是在引用一个函数,但 this 的值得到了维持,因为 object.getName 和(object.getName)的定义 是相同的。第三行代码先执行了一条赋值语句,然后再调用赋值后的结果。因为这个赋值表达式的值是 函数本身,所以 this 的值不能得到维持,结果就返回了"Windows"。
当然,你不大可能会像第二行和第三行代码一样调用这个方法。不过,这个例子有助于说明即使是 语法的细微变化,都有可能意外改变 this 的值。
闭包缺点
除了以上那么恶心的东西之外...最大的缺点还是暂用内存比较大,如果不是必要的还是慎用。
【JavaScript回顾】闭包的更多相关文章
- 深入理解JavaScript的闭包特性如何给循环中的对象添加事件
		初学者经常碰到的,即获取HTML元素集合,循环给元素添加事件.在事件响应函数中(event handler)获取对应的索引.但每次获取的都是最后一次循环的索引.原因是初学者并未理解JavaScript ... 
- JavaScript作用域闭包简述
		JavaScript作用域闭包简述 作用域 技术一般水平有限,有什么错的地方,望大家指正. 作用域就是变量起作用的范围.作用域包括全局作用域,函数作用域以块级作用域,ES6中的let和const可以形 ... 
- JavaScript的闭包原理
		什么是js(JavaScript)的闭包原理,有什么作用? 一.定义 官方解释:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分. 个人的理解是 ... 
- Js(javaScript)的闭包原理
		问题?什么是js(javaScript)的闭包原理,有什么作用? 一.定义 官方解释:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分. 小编 ... 
- 深入理解javascript的闭包
		闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域 ... 
- 如何给循环中的对象添加事件--深入理解JavaScript的闭包特性
		初学者经常碰到的,即获取HTML元素集合,循环给元素添加事件.在事件响应函数中(event handler)获取对应的索引.但每次获取的都是最后一次循环的索引.原因是初学者并未理解JavaScript ... 
- javascript,jquery(闭包概念)(转)
		偶尔听人说javascript闭包,让我联想起以前学编译原理和数字逻辑里讲的闭包,以前上课讲的闭包很难懂,而且含有递归的意思在里面,现在不想再查看里面的闭包概念. 但javascript我是经常要用, ... 
- 理解Javascript 的闭包(closure)
		要理解闭包的概念先从变量的作用域说去 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之 ... 
- 两个示例介绍JavaScript的闭包
		JavaScript的闭包有两个用途:一个是访问函数内部的变量:另一个是让变量的值在作用域内保持不变.函数是JavaScript 中唯一有作用域的对象,因此JavaScript的闭包依赖于函数实现,下 ... 
- javascript 关于闭包的知识点
		javascript 关于闭包的认识 概念:闭包(closure)是函数对象与变量作用域链在某种形式上的关联,是一种对变量的获取机制. 所以要大致搞清三个东西:函数对象(function object ... 
随机推荐
- Javascript的一个生产PDF的库: unicode和中文问题的解决
			Javascript的一个生产PDF的库: unicode和中文问题的解决基于canvas和jspdf库, 实现用javascript的支持中文pdf生成实用工具.参考:http://javascri ... 
- 地铁沉降观测数据分析之巧用VBA编程处理
			地铁沉降观测数据分析之巧用VBA编程处理 当你观测了一天累的要死了,回来看着成百上千的测量数据,还要做报表.如果是三五页报表还好说,如果是2000个点的报表 按照一页纸张报30个点就得大约70页的报表 ... 
- webdriver实用指南迁移至gitbbok并改名为selenium webdriver从入门到提高
			背景 几年前我写了一本关于selenium webdriver的小册子,主要讲了一些selenium在进行测试过程中会遇到的场景以及解决方案,陆陆续续在github上收到了100+的star,在这里我 ... 
- 是时候放弃sublime了
			今天下午在忍无可忍之下终于卸载了sublime,最为一个在gui下最顺手的编辑器,放弃是需要非常充足的理由的. 放弃sublime无非是因为以下几点原因: 收费.我用的是未注册版的sublime,保存 ... 
- RHEL 6 或者 Oracle Linux 6, 不关机识别新添加的scsi硬盘
			下面看一下在系统不重启的情况,如何让系统认识新的磁盘,并能对其分区与格式化1.在开机状态下新增磁盘2.执行下面的命令 echo "- - -" > /sys/class/sc ... 
- CGI、FastCGI 知识总结
			@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ... 
- idea启动tomcat失败,1099端口被占用
			今天遇到一个问题,当使用idea启动一个tomat服务的时候,报错:不能连接本地1099端口. /Users/liqiu/soft/develop/apache-tomcat-/bin/catalin ... 
- 再探 Ext JS 6 (sencha touch/ext升级版) 变化篇 (编译命令、滚动条、控制层、模型层、路由)
			从sencha touch 2.4.2升级到ext js 6,cmd版本升级到6.0之后发生了很多变化 首先从cmd说起,cmd 6 中sencha app build package不能使用了,se ... 
- vm导入后远程桌面无法登陆域账户
			以本地Admin账户登录,打开C:\Windows\System32\sysprep目录,运行sysprep.exe工具,勾选Generalize,点击OK.系统重启后对Windows重新初始化,生成 ... 
- [原]Android Native Debug
			1,安装adt插件,cdt插件2,SDK目录配置: Eclipse文件菜单选择“Window”--->“Preferences”--->“Android”--->设置“SDK Loc ... 
