关于javascript闭包的最通俗易懂的理解
这两天在研究闭包,网上一通找,有牛人写的帖子,有普通人写的帖子,但是大多没戳中本小白所纠结的点,而且大多插入了立即执行函数,其实根本不需要的,反而让人产生了误解。这里我用我的方式讲解一下闭包。
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闭包的最通俗易懂的理解的更多相关文章
- 深入理解javascript闭包(一)
		
闭包(closure)是Javascript语言的一个难点.也是它的特色,非常多高级应用都要依靠闭包实现. 一.什么是闭包? 官方"的解释是:闭包是一个拥有很多变量和绑定了这些变量的环境的表 ...
 - javascript 闭包(转)
		
一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 ...
 - JavaScript 闭包整合
		
初遇闭包感觉很困惑,上网查看了些许介绍,有很多没看懂,就想先对能懂的东西整整 首先觉得要了解闭包,要先对一.JavaScript的变量作用域和作用域链有基本了解 1.变量的作用域分为:全局变量和局部变 ...
 - 一篇文章图文并茂地带你轻松学完 JavaScript 闭包
		
JavaScript 闭包 为了更好地理解 JavaScript 闭包,笔者将先从 JavaScript 执行上下文以及 JavaScript 作用域开始写起,如果读者对这方面已经了解了,可以直接跳过 ...
 - JavaScript学习总结——我所理解的JavaScript闭包
		
一.闭包(Closure) 1.1.什么是闭包? 理解闭包概念: a.闭包是指有权限访问另一个函数作用域的变量的函数,创建闭包的常见方式就是在一个函数内部创建另一个函数,也就是创建一个内部函数,创建一 ...
 - JavaScript闭包理解【关键字:普通函数、闭包、解决获取元素标签索引】
		
以前总觉得闭包很抽象,很难理解,所以百度一下"闭包"概览,百度的解释是:“闭包是指可以包含自由(未绑定到特定对象)变量的代码块:这些变量不是在这个代码块内或者任何全局上下文中定义的 ...
 - javascript闭包理解
		
//闭包理解一 function superFun(){ var _super_a='a'; function subfuc(){ console.log(_super_a); } return su ...
 - javascript 闭包最简单理解
		
首先说3点与闭包有关系的东西. 一.变量的作用域 变量的作用域不难理解. 1.函数内部可以访问函数外部的变量,而函数外部不能访问函数内部的变量. 2.如果在函数内定义变量的时候,不加var,那么是全局 ...
 - 全面理解Javascript闭包和闭包的几种写法及用途
		
好久没有写博客了,过了一个十一长假都变懒了,今天总算是恢复状态了.好了,进入正题,今天来说一说javascript里面的闭包吧!本篇博客主要讲一些实用的东西,主要将闭包的写法.用法和用途. 一.什么 ...
 
随机推荐
- 挖穿各大SRC的短信轰炸
			
今天给大家分享一个短信轰炸绕过的姿势,大疆.百度.腾讯等等src都有用此方法绕过的案例. 给大家看一下 这里就不给大家截图了,在src中提交的截图都没有打码,这里放出来不太方便. 这里就只举出大疆的例 ...
 - 2019-2020-1 20199303《Linux内核原理与分析》第三周作业
			
操作系统是如何工作的 除了存储程序计算机和函数调用堆栈机制,还有一个非常基础的概念就是中断,这三个关键性的方法机制可以称作计算机的三个法宝:程序存储计算机.函数调用.中断 堆栈的作用:记录函数调用框架 ...
 - Spring 梳理-启用MVC
			
启用注解启动的Spring MVC xml <mvc:annotation-dirven> <mvc:annotation-driven /> 是一种简写形式,完全可以手动配置 ...
 - 命名对象继承1-验证Create*命名对象安全属性的传递
			
windows核心编程 第5版 48页 下半部写道 进程B调用CreateMutex时,它会向函数传递安全属性信息和第二参数.如果已经存在一个指定名称的对象,这些对象就会被忽略 于是我通过代码来验证这 ...
 - idea必备快捷键
			
ctrl + F: 在当前文件进行文本查找 ctrl + R: 在当前文件进行文本的替换 ctrl + Z: 撤销操作 ctrl + Y:删除光所在的行 或者选中的行 ctrl + D: 复制光标所在 ...
 - maven私服 nexus 的安装与使用
			
简介 私服不是Maven的核心概念,它仅仅是一种衍生出来的特殊的Maven仓库.通过建立自己的私服,就可以降低中央仓库负荷.节省外网带宽.加速Maven构建.自己部署构建等,从而高效地使用Maven. ...
 - .Net Core 商城微服务项目系列(七):使用消息队列(RabbitMQ)实现服务异步通信
			
RabbitMQ是什么,怎么使用我就不介绍了,大家可以到园子里搜一下教程.本篇的重点在于实现服务与服务之间的异步通信. 首先说一下为什么要使用消息队列来实现服务通信:1.提高接口并发能力. 2.保证 ...
 - php常用函数(第一版)
			
1.array_slice 作用:数组分页函数 案例:$output = array_slice ( $input , - 2 , 1 ); 2.array_column 作用:数组根据值取出一 ...
 - ELK 学习笔记之 Kibana安装
			
Kibana安装: 安装地址: https://www.elastic.co/downloads/kibana 安装: tar -zxvf kibana-5.6.1-linux-x86_64.tar. ...
 - Spring Boot2 系列教程(十)Spring Boot 整合 Freemarker
			
今天来聊聊 Spring Boot 整合 Freemarker. Freemarker 简介 这是一个相当老牌的开源的免费的模版引擎.通过 Freemarker 模版,我们可以将数据渲染成 HTML ...