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

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

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

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

round 1:

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

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

round 2:

//此处temp表示函数add函数本身,但是尚未执行。

var temp = function add() {
  var x = 0;
  return function () {
    return ++x;
  }
}; //执行temp函数,返回函数 function () {return ++x;},但尚未执行该函数,故x=0
var temp1 = temp(); //执行temp1,此时执行了一次function () {return ++x;},故x=1
temp1(); //再次执行一次function () {return ++x;},此时x=2,且输出到了控制台
console.log(temp1());

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

round 3:

/*仔细看,此处为(fucntion add(){})(),此处执行了立即执行函数,也就是说返回给temp的与round2返回的add函数本身不同,而是返回的 function () {return ++x;}*/

var temp = (function add() {
  var x = 0;
  return function () {
    return ++x;
  }
  })(); //顺理成章的,这里直接执行temp,就是执行了function () {return ++x;},故x=1
temp(); //同理x=2
console.log(temp());

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

这个是round1的改版:

function add() {
  var x = 0;
  return function () {
    return ++x;
  }
}; console.log(add()());//输出1 console.log(add()());//输出1

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

function add() {
var x = 0;
return function () {
return ++x;
}
}; var temp1 = add();
var temp2 = add();
console.log(temp1());//输出1
console.log(temp1());//输出2 console.log(temp2());//输出1
console.log(temp2());//输出2

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

function add() {
  var x = 0;
  return (function () {
    return ++x;
  })()
};

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

关于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. 数据分析--Matplotlib的基本使用

    一.Matplotlib概述 1.Matplotlib是一个强大的Python绘图和数据可视化的工具包. 2.python中操作方式: 安装方法:pip install matplotlib 引用方法 ...

  2. Micronaut 微服务中使用 Kafka

    今天,我们将通过Apache Kafkatopic构建一些彼此异步通信的微服务.我们使用Micronaut框架,它为与Kafka集成提供专门的库.让我们简要介绍一下示例系统的架构.我们有四个微型服务: ...

  3. Spring 梳理 - filter、interceptor、aop实现与区别 -第一篇

    前言 项目中我们经常需要对RESTful api进行拦截,主流实现方法有filter.interceptor.aop,先说一下他们各自的实现. Filter AnimalFilter实现javax.s ...

  4. Idea 配置Jrebel热部署

    虽说Idea自带热更新功能,但是一旦mapper更改,则不能及时更新,影响开发效率. 接下来,我们来配置Jrebel热更新,简单方便实用. 第一步:进入插件下载页面. 第二步:安装jrebel插件. ...

  5. Java 基础篇之反射

    反射 使用反射获取程序运行时的对象和类的真实信息. 获取 Class 对象 每个类被加载之后,系统会为该类生成一个对应的 Class 对象,通过该 Class 对象可以访问到 JVM 中的这个类. 使 ...

  6. WebGL简易教程(八):三维场景交互

    目录 1. 概述 2. 实例 2.1. 重绘刷新 2.2. 鼠标事件调整参数 3. 结果 4. 参考 1. 概述 在上一篇教程<WebGL简易教程(七):绘制一个矩形体>中,通过一个绘制矩 ...

  7. springcloud --- spring cloud sleuth和zipkin日志管理(spring boot 2.18)

    前言 在spring cloud分布式架构中,系统被拆分成了许多个服务单元,业务复杂性提高.如果出现了异常情况,很难定位到错误位置,所以需要实现分布式链路追踪,跟进一个请求有哪些服务参与,参与的顺序如 ...

  8. Creator3D长什么样?看看官方惊艳的DEMO就知道了,附在线体验!

    Shawn 这两天在学习 Creator3D 的官方案例,由于是刚接触 Creator3D 很多东西在没弄清楚之前还是以简单的编辑介绍为主,先了解一下3D场景的基本操作: 观查场景:按住鼠标右键以自己 ...

  9. Kafka 学习笔记之 架构

    Kafka的概念: 1. AMQP协议 Advanced Message Queuing Protocol (高级消息队列协议) The Advanced Message Queuing Protoc ...

  10. JS中的排序算法-冒泡排序解析

    冒泡排序算法 例子:10,8,9,6,4,20,5  从小到大排序 第一轮  1)10>8  交换数据 得到:8,10,9,6,4,20,5 2)10>9  交换数据 得到:8,9,10, ...