理解了上下文环境、作用域、作用域链以及自由变量,我们再来聊聊闭包

我们不急于给出闭包的概念,先从应用闭包的两种情况 —— 1.函数作为返回值,2.函数作为参数被传递 —— 来直观的认识它。

第一,函数作为返回值

function fn() {var max = 10;return function bar(x) {if( x > max ) {console.log(x);}};
}var f1 = fn();
f1(15);

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

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

var max = 10,fn = function(x) {console.log( x > max ? true : false );};(function(f) {var max = 100;f(20);
})(fn);

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

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

以上是从作用域的角度对闭包的理解,我们还可以结合执行上下文栈来理解闭包。

在前面讲执行上下文栈时说到,有些情况下,函数调用完成之后,其执行上下文环境不会接着被销毁。这就是需要理解闭包的核心内容。

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

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

图片描述

第二步,执行第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行就是上下文环境的销毁过程,这里就不再赘述了。

深入理解JavaScript (5) —— 闭包相关推荐

  1. 深入理解javascript的闭包

    闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域 ...

  2. 深入理解JavaScript的闭包特性如何给循环中的对象添加事件

    初学者经常碰到的,即获取HTML元素集合,循环给元素添加事件.在事件响应函数中(event handler)获取对应的索引.但每次获取的都是最后一次循环的索引.原因是初学者并未理解JavaScript ...

  3. 如果理解Javascript利用闭包循环绑定事件

    我们先看一个关于Javascript利用循环绑定事件的例子: 例如:一个不确定长度的列表,在鼠标经过某一条的时候改变背景. <!DOCTYPE html PUBLIC "-//W3C/ ...

  4. [转载]深入理解JavaScript闭包(closure)

    最近在网上查阅了不少Javascript闭包(closure)相关的资料,写的大多是非常的学术和专业.对于初学者来说别说理解闭包了,就连文字叙述都很难看懂.撰写此文的目的就是用最通俗的文字揭开Java ...

  5. 深入理解JavaScript闭包(closure) 【收藏】

    深入理解JavaScript闭包(closure) 原文地址:http://www.felixwoo.com/archives/247  Felix Woo 最近在网上查阅了不少Javascript闭 ...

  6. 【转】深入理解JavaScript闭包(closure)

    文章来源:http://www.felixwoo.com/archives/247 最近在网上查阅了不少Javascript闭包(closure)相关的资料,写的大多是非常的学术和专业.对于初学者来说 ...

  7. 让你分分钟理解 JavaScript 闭包

    原文:https://www.cnblogs.com/onepixel/p/5062456.html 让你分分钟理解 JavaScript 闭包 闭包,是 Javascript 比较重要的一个概念,对 ...

  8. 全面理解Javascript闭包和闭包的几种写法及用途--转载自https://www.cnblogs.com/yunfeifei/p/4019504.html...

    全面理解Javascript闭包和闭包的几种写法及用途 好久没有写博客了,过了一个十一长假都变懒了,今天总算是恢复状态了.好了,进入正题,今天来说一说javascript里面的闭包吧!本篇博客主要讲一 ...

  9. 深入理解Javascript闭包(一)

    闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用于.变量作用域包括 ...

  10. 深入理解javascript原型和闭包(16)——完结

    之前一共用15篇文章,把javascript的原型和闭包. 首先,javascript本来就"不容易学".不是说它有多难,而是学习它的人,往往都是在学会了其他语言之后,又学java ...

最新文章

  1. Cocoa 框架 For iOS(二)对象的分配初始化、内省、单例
  2. 如果通过当前元素知道父元素、同级元素
  3. JVM专题(2)-类加载器子系统
  4. 【深度学习】深度学习中的知识蒸馏技术(上)简介
  5. MFC中打开文件对话框:CFileDlg
  6. echarts的词云图表类型有哪些_数据可视化之常见12种图表类型分析
  7. JDK源码包结构分类
  8. python爬虫数据可视化软件_python爬虫及数据可视化分析
  9. 清除tomcat缓存
  10. python正则表达式re模块_详解Python正则表达式re模块
  11. java入门到精通6版pdf_java从入门到精通第6章.pdf
  12. JS实现图片拖动验证
  13. anguarjs 图片预览_一键精准提取图片文字,这么高效的app确定不盘一下嘛
  14. Twaver-HTML5基础学习(26)背景
  15. 新型智能优化算法——海鸥优化算法(基于Matlab代码实现)
  16. coldwallet java eth,使用Web3j(JAVA)开发ETH钱包-2
  17. Deamon有名的守护进程
  18. 科学与财富杂志科学与财富杂志社科学与财富编辑部2022年第27期目录
  19. Mybatis的一个连接mysql的坑
  20. 基于单片机控制的开关电源设计

热门文章

  1. VS2010制作dll
  2. SonarLint各种提示的意思
  3. 201421410019 杨光裕 实验一
  4. 4. 实例palybook安装管理flume
  5. 设计模式学习一:strategyPattern
  6. 使用CSS实现透明边框的效果——兼容当前各种主流浏览器[xyytIT]
  7. javabean封装mysql
  8. [恢]hdu 2062
  9. 全屏显示一个图片文件
  10. 独家分享--48页PPT解密数据可视化!