第九十九篇:JS闭包
好家伙,总是要来的,去面对那些晦涩难懂的原理,它就在那里,等着我去搞定它
首先我要去补充一些最基本的概念,
1.什么是内存?

新华字典永远的神,
但这个解释显然不够
去看看百度百科:
内存:
CPU 能 直接寻址 的 存储空间
2.变量的储存机制
所以,我们假设现在写了一行代码:
var a = 2;
我们将它拆解为两部分
var a;
和
a=2;
说人话就是:为一个变量分配内存,将其命名为a,然后将2保存进这个变量
接着上面的话就是:为一个变量分配CPU 能 直接寻址 的 存储空间,将其命名为a,然后将2保存进这个CPU 能 直接寻址 的 存储空间
3.变量的销毁机制
当一个变量不被需要的时候,就会被销毁,
全局变量不会被销毁,
4.编译原理
var a =2;
这样复杂的语言的,机器是无法理解的
所以我们会需要编译器,
编辑器来这里只干三件事
4.1.词法分析
这个过程将由字符组成的字符串分解成有意义的代码块
4.2.语法分析
这个过程是将此番单元六转换成一个有元素逐级嵌套所组成的代表了程序语法的结构的数
4.3.代码生成
转换成机器能听的懂得语言
这个其实好理解,就像做英语翻译一样
sun of beach分三步翻译
第一步:拆开 sun,of和beach
第二步:XXX of XXX语法
第三步:sun是太阳 of是...的 beach是沙滩
所以翻译就是 沙滩阳光
然后我就能听懂了


5.什么是作用域?
还是那个变量a
我们会这个变量a进行很多操作,例如加减乘除
而当我们操作的时候,我们如何找到他们?
我们需要一套设计良好的规则来储存变量,并且之后可以方便地找到这些变量,
这套规则被称为作用域
----摘自<<你不知道的js(上)>>
作用域指的是当前有权访问的变量集合。
JavaScript 拥有函数作用域:每个函数创建一个新的作用域。 作用域决定了这些变量的可访问性(可见性)。
简单的来说,就是:
全局变量全局都能用,
局部变量如下:
// 此处的代码不能使用 carName 变量
function myFunction() {
var carName = "porsche";
// 此处的代码能使用 carName 变量
}
只有局部能用
6.理解闭包
(本篇的主角终登场了)
来看一段展示闭包的代码:
function foo(){
var a =2;
function bar(){
console.log(a);
}
return bar;
}
var baz = foo();
baz();
//此处输出的结果:2
函数
函数bar()的词法作用域能够访问foo()的内部作用域。
然后我们将bar()函数本身当作一个值类型进行传递。
在这个例子中,我们将bar所引用的函数对象本身当作返回值。
在foo()执行后,其返回值(也就是内部的bar()函数)赋值给变量baz并调用baz(),
实际上只是通过不同的标识符引用调用了内部的函数bar()。
bar()显然可以被正常执行。但是在这个例子中,它在自己定义的词法作用域以外的地方执行。
在foo()执行后,通常会期待foo()的整个内部作用域都被销毁,
因为我们知道引擎有垃圾回收器用来释放不再使用的内存空间。
由于看上去foo()的内容不会再被使用,所以很自然地会考虑对其进行回收。
而闭包的“神奇”之处正是可以阻止这件事情的发生。事实上内部作用域依然存在,因此没有被回收。
谁在使用这个内部作用域?原来是bar()本身在使用。
拜bar()所声明的位置所赐,它拥有涵盖foo()内部作用域的闭包,
使得该作用域能够一直存活,以供bar()在之后任何时间进行引用。
bar()依然持有对该作用域的引用,而这个引用就叫作闭包。
因此,在几微秒之后变量baz被实际调用(调用内部函数bar),
不出意外它可以访问定义的时候语法作用域,因此它也可以如预期般访问变量a
这个函数在定义时的词法作用域以外的地方被调用.闭包使得函数可以继续访问定义时的词法作用域
----摘自<<你不知道的js(上)>>
所以,什么是闭包?
一个函数可引用该函数外部的变量,
function foo(){
var a =2;
function bar(){
console.log(a);
}
return bar;
}
var baz = foo();
baz();
我要用自己的话说一遍确保我自己理解了:
我调用baz()了,baz()被赋值了,我调用foo(),foo()返回一个bar,bar,打印a
bar把foo的作用域带到了baz中,这个过程发生了闭包,baz用到了变量a
大概就是这样
第九十九篇:JS闭包的更多相关文章
- 第十九篇 js高级知识---词法分析和AO 链
上面一篇文章说了js的作用域链,这一节算是对上面的延申,有一个典型的例子,首先看原来的一段代码: var name = "test"; function t() { var b = ...
- Egret入门学习日记 --- 第十九篇(书中 8.8~8.10 节 内容)
第十九篇(书中 8.8~8.10 节 内容) 开始 8.8节. 重点: 1.类型推断. 2.类型强制转换,使其拥有代码提示功能. 3.除了TS自带的类型判断,Egret官方也提供了类型判断的方法. 操 ...
- Python之路【第十九篇】:爬虫
Python之路[第十九篇]:爬虫 网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本.另外一些不常使用 ...
- Bootstrap入门(二十九)JS插件6:弹出框
Bootstrap入门(二十九)JS插件6:弹出框 加入小覆盖的内容,像在iPad上,用于存放非主要信息 弹出框是依赖于工具提示插件的,那它也和工具提示是一样的,是需要初始化才能够使用的 首先我们引入 ...
- “全栈2019”Java第九十九章:局部内部类与继承详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- Android UI开发第三十九篇——Tab界面实现汇总及比较
Tab布局是iOS的经典布局,Android应用中也有大量应用,前面也写过Android中TAb的实现,<Android UI开发第十八篇——ActivityGroup实现tab功能>.这 ...
- 第九十六篇:恶补JS基础
好家伙,来补基础啦,补JS的基础 先来一些概念性的东西 1.什么是JavaScript? javaScript的简写形式就是JS,一种广泛用于客户端Web开发的脚本语言,常用来给HTML网页添加动态 ...
- 第十九篇 -- QTableWidget的使用
QTableWidget的一些常用方法 下面两个类可以根据自己的情况自定义. 单元格类型的类: class CellType(Enum): ctKey = 1000 ctPath = 1001 ctI ...
- Python开发【第十九篇】:Python操作MySQL
本篇对于Python操作MySQL主要使用两种方式: 原生模块 pymsql ORM框架 SQLAchemy pymsql pymsql是Python中操作MySQL的模块,其使用方法和MySQLdb ...
随机推荐
- electron-vue 项目启动动态获取配置文件中的后端服务地址
前言 最近的项目迭代中新增一个需求,需要在electron-vue 项目打包之后,启动exe 可执行程序的时候,动态获取配置文件中的 baseUrl 作为服务端的地址.electron 可以使用 no ...
- 领导:谁再用redis过期监听实现关闭订单,立马滚蛋!
日前拜读阿牛老师的大作 领导:谁再用定时任务实现关闭订单,立马滚蛋! 发现其方案有若干瑕疵,特此抛砖引玉讨论一二. 在电商.支付等领域,往往会有这样的场景,用户下单后放弃支付了,那这笔订单会在指定的时 ...
- 从0到1搭建一款页面自适应组件(Vue.js)
组件将根据屏幕比例及当前浏览器窗口大小,自动进行缩放处理. 建议在组件内使用百分比搭配flex进行布局,以便于在不同的分辨率下得到较为一致的展示效果.使用前请注意将body的margin设为0,否则会 ...
- Freeswitch使用originate转dialplan
概述 Freeswitch是一款非常好用的开源VOIP软交换平台. 最近在对fs做一些功能测试,测试的过程中产生的一个需求,如何从fs发起呼叫并把后续的呼叫流程转到某一个dialplan上,这样在测试 ...
- 158_模型_Power BI 使用 DAX + SVG 打通制作商业图表几乎所有可能
158_模型_Power BI 使用 DAX + SVG 打通制作商业图表几乎所有可能 一.背景 最近对 Power BI 中使用 SVG 比较感兴趣,今天我们使用 DAX + SVG 复刻一下 Ze ...
- 如何修改 node_modules 里的文件
前言 有时候使用npm上的包,发现有bug,我们知道如何修改,但是别人可能一时半会没法更新,或者是我们特殊需求,别人不愿意修改,这时候我们只能自己动手丰衣足食.那么我们应该如何修改别人的源码呢?首先, ...
- 深入理解 volatile 关键字
volatile 关键字是 Java 语言的高级特性,但要弄清楚其工作原理,需要先弄懂 Java 内存模型.如果你之前没了解过 Java 内存模型,那可以先看看之前我写过的一篇「深入理解 Java 内 ...
- Python教程——常用的os操作详情
Python自动的os库是和操作系统交互的库,常用的操作包括文件/目录操作,路径操作,环境变量操作和执行系统命令等. 文件/目录操作 获取当前目录(pwd): os.getcwd() 切换目录(cd) ...
- 《Ranked List Loss for Deep Metric Learning》CVPR 2019
Motivation: 深度度量学习的目标是学习一个嵌入空间来从数据点中捕捉语义信息.现有的成对或者三元组方法随着模型迭代过程会出现大量的平凡组导致收敛缓慢.针对这个问题,一些基于排序结构的损失取得了 ...
- 挑战30天写操作系统-day3-进入32位模式并导入C语言
目录 1.制作真正的IPL IPL:启动区,启动程序装载器完整代码: ; haribote-ipl ; TAB=4 CYLS EQU 10 ; 声明CYLS=10 ORG 0x7c00 ; 指明程序装 ...