这两天在研究闭包,网上一通找,有牛人写的帖子,有普通人写的帖子,但是大多没戳中本小白所纠结的点,而且大多插入了立即执行函数,其实根本不需要的,反而让人产生了误解。这里我用我的方式讲解一下闭包。

1.目的:保证局部变量常驻在内存中,且只能通过固定的方式访问,不可以被所有人访问,算起来也算是个只能被指定对象访问的专用型全局变量。

2.实现方式:在函数f1中返回一个内部定义的函数f2,后通过使用返回出来的函数f2来操作f1中定义的局部变量。

下面我来从各种刁钻的角度来举例详细说明,包学包会!看完例子以后再看上面说的目的和实现方式就会有种豁然开朗的感觉了!

round 1:

  1. function add() {
  2.   var x = 0;
  3.   return function () {
  4.     return ++x;
  5.   }
  6. };
  7.  
  8. /*此处的add()的括号和function add()的括号表达的意思是完全不同的, 在此处add表示上
  9. 面定义的函数,add()表示执行一次上面定义的函 数,这一点很关键!执行一次的结果就是返回了函数 function () {return ++x;},但是请注意!这里返回的仅仅是函数本 身,也就是此时函数尚未执行,故此时x=0*/
  10. var temp=add();
  11.  
  12. //执行一次返回的函数,++x,此时x=1
  13. temp();
  14.  
  15. //再次执行一次返回的函数,此时x=2,且输出了函数的返回值2,可以在控制台中看到
  16. console.log(temp());

这就完成了闭包了,add函数中的x常驻内存,且我可以在add函数外部通过调用它返回的函数来操作这个x,如果看懂了下面可以不看,如果看了其他帖子有一些其他的异或比如立即执行函数之类的可以看看下面的,你很快就不会疑惑了!

round 2:

  1. //此处temp表示函数add函数本身,但是尚未执行。
  2.  
  3. var temp = function add() {
  4.   var x = 0;
  5.   return function () {
  6.     return ++x;
  7.   }
  8. };
  9.  
  10. //执行temp函数,返回函数 function () {return ++x;},但尚未执行该函数,故x=0
  11. var temp1 = temp();
  12.  
  13. //执行temp1,此时执行了一次function () {return ++x;},故x=1
  14. temp1();
  15.  
  16. //再次执行一次function () {return ++x;},此时x=2,且输出到了控制台
  17. console.log(temp1());

这一回合是为下面的立即执行函数做铺垫,下面立即执行函数版本隆重登场!当当当当!

round 3:

  1. /*仔细看,此处为(fucntion add(){})(),此处执行了立即执行函数,也就是说返回给temp的与round2返回的add函数本身不同,而是返回的 function () {return ++x;}*/
  2.  
  3. var temp = (function add() {
  4.   var x = 0;
  5.   return function () {
  6.     return ++x;
  7.   }
  8.   })();
  9.  
  10. //顺理成章的,这里直接执行temp,就是执行了function () {return ++x;},故x=1
  11. temp();
  12.  
  13. //同理x=2
  14. console.log(temp());

经过上面三个例子的讲解想必你已经心中有数了,但是肯定还是存在疑惑的,比如说round1中var temp=add();,我不把add()的结果赋给temp直接执行行不行?答案是否定的,有一点一定要认知清楚,函数是对象,这一点至关重要,否则将会走入误区。下面举例说明:

这个是round1的改版:

  1. function add() {
  2.   var x = 0;
  3.   return function () {
  4.     return ++x;
  5.   }
  6. };
  7.  
  8. console.log(add()());//输出1
  9.  
  10. console.log(add()());//输出1

为什么会这样呢?关键点在于函数是对象,上面实行了两次add()(),在这两次中,add()返回的对象是不一样的,所以他们各自再执行add()()就是为各自的局部变量x加1,所以才两次都输出1,假如改一下

  1. function add() {
  2. var x = 0;
  3. return function () {
  4. return ++x;
  5. }
  6. };
  7.  
  8. var temp1 = add();
  9. var temp2 = add();
  10. console.log(temp1());//输出1
  11. console.log(temp1());//输出2
  12.  
  13. console.log(temp2());//输出1
  14. console.log(temp2());//输出2

这样是不是就明白了,同理add函数也不能写成下面这种形式:

  1. function add() {
  2.   var x = 0;
  3.   return function () {
  4.     return ++x;
  5.   })()
  6. };

否则返回的只是一个常量而不是一个对象了。希望这篇文章能给跟我一样在摸索闭包的小白一点启发,嘿嘿嘿

关于javascript闭包的最通俗易懂的理解的更多相关文章

  1. 深入理解javascript闭包(一)

    闭包(closure)是Javascript语言的一个难点.也是它的特色,非常多高级应用都要依靠闭包实现. 一.什么是闭包? 官方"的解释是:闭包是一个拥有很多变量和绑定了这些变量的环境的表 ...

  2. javascript 闭包(转)

    一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 ...

  3. JavaScript 闭包整合

    初遇闭包感觉很困惑,上网查看了些许介绍,有很多没看懂,就想先对能懂的东西整整 首先觉得要了解闭包,要先对一.JavaScript的变量作用域和作用域链有基本了解 1.变量的作用域分为:全局变量和局部变 ...

  4. 一篇文章图文并茂地带你轻松学完 JavaScript 闭包

    JavaScript 闭包 为了更好地理解 JavaScript 闭包,笔者将先从 JavaScript 执行上下文以及 JavaScript 作用域开始写起,如果读者对这方面已经了解了,可以直接跳过 ...

  5. JavaScript学习总结——我所理解的JavaScript闭包

    一.闭包(Closure) 1.1.什么是闭包? 理解闭包概念: a.闭包是指有权限访问另一个函数作用域的变量的函数,创建闭包的常见方式就是在一个函数内部创建另一个函数,也就是创建一个内部函数,创建一 ...

  6. JavaScript闭包理解【关键字:普通函数、闭包、解决获取元素标签索引】

    以前总觉得闭包很抽象,很难理解,所以百度一下"闭包"概览,百度的解释是:“闭包是指可以包含自由(未绑定到特定对象)变量的代码块:这些变量不是在这个代码块内或者任何全局上下文中定义的 ...

  7. javascript闭包理解

    //闭包理解一 function superFun(){ var _super_a='a'; function subfuc(){ console.log(_super_a); } return su ...

  8. javascript 闭包最简单理解

    首先说3点与闭包有关系的东西. 一.变量的作用域 变量的作用域不难理解. 1.函数内部可以访问函数外部的变量,而函数外部不能访问函数内部的变量. 2.如果在函数内定义变量的时候,不加var,那么是全局 ...

  9. 全面理解Javascript闭包和闭包的几种写法及用途

    好久没有写博客了,过了一个十一长假都变懒了,今天总算是恢复状态了.好了,进入正题,今天来说一说javascript里面的闭包吧!本篇博客主要讲一些实用的东西,主要将闭包的写法.用法和用途.  一.什么 ...

随机推荐

  1. Linux 部署vsftp服务及详解

    一.FTP服务概述: FTP服务器(File Transfer Protocol Server)是在互联网上提供文件存储和访问服务的计算机,它们依照FTP协议提供服务. FTP(File Transf ...

  2. SpringBootSecurity学习(11)网页版登录之URL动态权限

    动态权限 前面讨论用户登录认证的时候,根据用户名查询用户会将用户拥有的角色一起查询出来,自动实现判断当前登录用户拥有哪些角色.可以说用户与角色之间的动态配置和判断security做的非常不错.不过在配 ...

  3. 基于 HTML5 和 WebGL 的地铁站 3D 可视化系统

    前言 工业互联网,物联网,可视化等名词在我们现在信息化的大背景下已经是耳熟能详,日常生活的交通,出行,吃穿等可能都可以用信息化的方式来为我们表达,在传统的可视化监控领域,一般都是基于 Web SCAD ...

  4. C语言I博客作业

    |这个作业属于哪个课程 | C语言程序设计I | | ---- | ---- | |对这个作业要求在哪里 | https://edu.cnblogs.com/campus/zswxy/SE2019-2 ...

  5. uC/OS-III 时间管理(二)

    时间管理就是一种建立在时钟节拍上,对操作系统任务的运行实现时间上管理的一种系统内核机制. 常用以下五个函数: OSTimeDly() OSTimeDlyHMSM() OSTimeDlyResume() ...

  6. WebGL简易教程(七):绘制一个矩形体

    目录 1. 概述 2. 示例 2.1. 顶点索引绘制 2.2. MVP矩阵设置 2.2.1. 模型矩阵 2.2.2. 投影矩阵 2.2.3. 视图矩阵 2.2.4. MVP矩阵 3. 结果 4. 参考 ...

  7. 夯实Java基础系列19:一文搞懂Java集合类框架,以及常见面试题

    本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...

  8. 品Spring:对@Resource注解的处理方法

    @Resource是Java的注解,表示一个资源,它具有双向的含义,一个是从外部获取一个资源,一个是向外部提供一个资源. 这其实就对应于Spring的注入和注册.当它用在字段和方法上时,表示前者.当它 ...

  9. 4、pytest 中文文档--pytest-fixtures:明确的、模块化的和可扩展的

    目录 1. fixture:作为形参使用 2. fixture:一个典型的依赖注入的实践 3. conftest.py:共享fixture实例 4. 共享测试数据 5. 作用域:在跨类的.模块的或整个 ...

  10. ThoughtWorks 面试三连挂,以后再也不去了

    先说我吧,之前在外企呆过两年,那时Team的很多同事都去了ThoughtWorks,所以有一种情怀,只要有机会我就去面试...之前在Team里对我的评价也很高(不是我说的),现在也是公司的技术总监,总 ...