转:javascript闭包的理解

转载 2016年08月28日 22:42:33

原文地址:点击打开链接

前面提到的上下文环境和作用域的知识,除了了解这些知识之外,还是理解闭包的基础。

至于“闭包”这个词的概念的文字描述,确实不好解释,我看过很多遍,但是现在还是记不住。

但是你只需要知道应用的两种情况即可——函数作为返回值,函数作为参数传递。

第一,函数作为返回值

如上代码,bar函数作为返回值,赋值给f1变量。执行f1(15)时,用到了fn作用域下的max变量的值。至于如何跨作用域取值,可以参考上一节。

 

第二,函数作为参数被传递

如上代码中,fn函数作为一个参数被传递进入另一个函数,赋值给f参数。执行f(15)时,max变量的取值是10,而不是100。

 

上一节讲到自由变量跨作用域取值时,曾经强调过:要去创建这个函数的作用域取值,而不是“父作用域”。理解了这一点,以上两端代码中,自由变量如何取值应该比较简单。(不明白的朋友一定要去上一节看看,这个很重要!

 

另外,讲到闭包,除了结合着作用域之外,还需要结合着执行上下文栈来说一下。

在前面讲执行上下文栈时(http://www.cnblogs.com/wangfupeng1988/p/3989357.html),我们提到当一个函数被调用完成之后,其执行上下文环境将被销毁,其中的变量也会被同时销毁。

但是在当时那篇文章中留了一个问号——有些情况下,函数调用完成之后,其执行上下文环境不会接着被销毁。这就是需要理解闭包的核心内容

咱们可以拿本文的第一段代码(稍作修改)来分析一下。

 

第一步,代码执行前生成全局上下文环境,并在执行时对其中的变量进行赋值。此时全局上下文环境是活动状态。

 

第二步,执行第17行代码时,调用fn(),产生fn()执行上下文环境,压栈,并设置为活动状态。

 

第三步,执行完第17行,fn()调用完成。按理说应该销毁掉fn()的执行上下文环境,但是这里不能这么做。注意,重点来了:因为执行fn()时,返回的是一个函数。函数的特别之处在于可以创建一个独立的作用域。而正巧合的是,返回的这个函数体中,还有一个自由变量max要引用fn作用域下的fn()上下文环境中的max。因此,这个max不能被销毁,销毁了之后bar函数中的max就找不到值了。

因此,这里的fn()上下文环境不能被销毁,还依然存在与执行上下文栈中。

——即,执行到第18行时,全局上下文环境将变为活动状态,但是fn()上下文环境依然会在执行上下文栈中。另外,执行完第18行,全局上下文环境中的max被赋值为100。如下图:

 

第四步,执行到第20行,执行f1(15),即执行bar(15),创建bar(15)上下文环境,并将其设置为活动状态。

执行bar(15)时,max是自由变量,需要向创建bar函数的作用域中查找,找到了max的值为10。这个过程在作用域链一节已经讲过。

这里的重点就在于,创建bar函数是在执行fn()时创建的。fn()早就执行结束了,但是fn()执行上下文环境还存在与栈中,因此bar(15)时,max可以查找到。如果fn()上下文环境销毁了,那么max就找不到了。

使用闭包会增加内容开销,现在很明显了吧

 

第五步,执行完20行就是上下文环境的销毁过程,这里就不再赘述了。

 

闭包和作用域、上下文环境有着密不可分的关系,真的是“想说爱你不容易”!

另外,闭包在jQuery中的应用非常多,在这里就不一一举例子了。所以,无论你是想了解一个经典的框架/类库,还是想自己开发一个插件或者类库,像闭包、原型这些基本的理论,是一定要知道的。否则,到时候出了BUG你都不知道为什么,因为这些BUG可能完全在你的知识范围之外。

深入理解JavaScript函数参数(推荐)

js的函数很特变,懂得一下这些才能玩转js函数的奥妙。。 正文开始~ ---------------------------------------------------------------...
  • u012028371
  • u012028371
  • 2017年04月13日 09:57
  • 381

js中对this关键字的理解

this是Javascript语言的一个关键字。它代表函数运行时,自动生成的一个内部对象,只能在**函数内部使用**。 比如, 理解this指代什么的关键点在与: 看这个this指的是局部对象还是全局...
  • SprintMan
  • SprintMan
  • 2016年11月09日 23:24
  • 1085

javascript中的面向对象理解(一)

一、注意:提到“面向对象”这一概念,众所周知,javascript中的面向对象思想与其他的编程语言(例如:PHP、Java等)是有着很大区别的。因此,我们先复习下,传统意义上,面向对象的相关概念,以便...
  • u014516981
  • u014516981
  • 2016年10月19日 23:48
  • 1888

如何理解和应用闭包

何为闭包 函数内部又定义了一个函数,这个子函数就可以称为闭包。 闭包的特点 闭包的一个特点就是闭包内部可以引用外部函数的变量。 原理 要理解闭包的原理,最重要的是要理解J...
  • qiupu4667
  • qiupu4667
  • 2017年04月12日 20:26
  • 320

对javascript匿名函数的理解(透彻版)

Query片段: view plaincopy to clipboardprint? (function(){  //这里忽略jQuery所有实现  })();     半...
  • abc1415035017
  • abc1415035017
  • 2015年01月11日 21:06
  • 590

如何理解Javascript中的闭包问题

闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现。 下面就是我的学习笔记,对于Javascript初学者应该是很有用的。 一、变量的作用域...
  • dihuiqin
  • dihuiqin
  • 2016年08月18日 13:16
  • 123

Javascript 实现gb2312和utf8编码的互换

转载地址 function getCodeStr(){  return codestr; }   function gb2utf(gbStr){  var codeStr = getC...
  • andrew57
  • andrew57
  • 2014年12月08日 11:53
  • 9808

javascript闭包的理解

1.闭包内部函数可以访问外部函数的变量,但是外部函数不能访问内部函数的变量。 function f1(){     var n=999;     function f2(){       alert(...
  • liuwengai
  • liuwengai
  • 2016年06月24日 22:14
  • 303

强大的JS转C#工具脚本:

强大的JS转C#工具脚本: 点击要转换的JS脚本,然后在菜单栏上执行这个脚本就可以自动转换生成一个新的C#文件。 using UnityEngine; using UnityEditor; ...
  • Highning0007
  • Highning0007
  • 2014年07月20日 14:14
  • 6430

彻底理解JavaScript原型

 原型是JavaScript中一个比较难理解的概念,原型相关的属性也比较多,对象有"[[prototype]]"属性,函数对象有"prototype"属性,原型对象有"constructor...
  • wxw_317
  • wxw_317
  • 2015年11月03日 16:14
  • 5618
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:转:javascript闭包的理解
举报原因:
原因补充:

(最多只允许输入30个字)