浅谈Javascript闭包
垃圾回收器
我个人把闭包抽象的称之为”阻止垃圾回收器的函数”或者”有权访问另一个函数内部变量的函数"(当然这个是我个人的理解方式,每个人可能会有不同的理解方式),为什么这样说?这样说还得说说垃圾回收器,一些编程语言如C语言对于内存管理是由程序员说了算,也就是说程序员决定这个变量是否还需要,如果不需要就释放这个变量占用的空间,而这个变量也不复存在了,这样做的好处是可以及时释放内存空间,让那些需要使用内存空间的程序来使用。
而在Javascript中,我们是不需要这样做的,Javascript有一个叫”垃圾回收器”的系统,它会自动对于那些我们不再使用的变量进行回收。那问题来了,它怎么知道我们不再需要这个变量了?在Javascript里面有两个回收机制一个为:”引用计数”,另外一个为"标记清除",垃圾回收器会根据代码里面对变量的调用(引用)来判断,如果这个变量的调用(引用)为0那么就表示可以回收了。
引用计数
引用计数是如何工作?拿一个例子来说吧:
“有一家公司的小明,他工作是和销售有关的,所以他每天会开公司的车去见客户、接客户进行推销。而取得公车的步骤需要向管车的王大爷进行预约,然后王大爷会把预约纪录到今天的预约表上,使用完后需要把车交给王大爷并把记录划掉。有一天小明需要使用公车,小明打电话给王大爷表明他下午两点会使用公车,王大爷随后把此次预约纪录到了今天的预约表上,到了约定时间,小明取到了公车。随后与客户一番见面商谈过后把公车交还给王大爷,王大爷同时也把预约表上的小明这一条记录给划掉,王大爷随后看了看预约表,今天没有人预约了,看来可以早点下班了,于是把车停回车库下班了。”
其实上面的例子可以看出来,王大爷相当于”垃圾回收器”,而王大爷依据什么来进行处理回收的?是根据预约表,而这个预约表就相当于”引用计数”,当这个预约表上没有人预约公车的时候,王大爷就把车停回了车库,当然如果还有预约王大爷还得一直等待预约表上没有任何预约了才能把车停回车库并下班。也就相当于当这个变量没有人在需要使用的时候,这个变量就可以被“回收”了。
标记清除
这一节点很感谢"linkFly"前辈指出我的错误,我错误的把"引用计数"理解为最常用的计数了,所以在这里感谢"linkFly"前辈。
目前"标记清除"技术是最常用的一种内存回收机制,现在chrome和Safari以及新版本IE、opera等浏览器均采用这样的内存回收机制。
"标记清除"不同于"引用计数",标记清除更加简单,相当于告诉我们这个变量能使用或者不能用。当一个变量声明的时候,变量会被标记为"进入环境",而当变量离开了环境过后就标记为"离开环境"。
标记清除的工作方式大概为:
首先javascript会在全局中给所有的变量加上标记,然后去掉在环境中的变量以及环境中被引用的变量的标记,其他被标记的变量表示可以清除的变量,在垃圾回收器执行的时候将会把这些变量清除掉。
什么是闭包?
在正常的回收机制下,当我们不再使用这个函数或者变量的时候就会被回收,不再使用是指在当前我们执行的状态之后没有出现在调用(引用)变量的语句了。下面有一个例子,简单的介绍了一下闭包,例子中logHello被赋值一个自执行匿名函数返回的函数,这个函数是有权限访问自执行匿名函数内部的log_num变量的,这样的函数被称为闭包,因为返回的函数内部有一个对自执行匿名函数内部log_num变量的引用。
var logHello;
logHello = ( function () {
var log_num = 20;
return function() {
return log_num;
};
} )();
下面还有一个例子,logHello被赋值自执行函数返回的一个对象,这个对象里面包含了两个方法”read”和”write”,这两个方法都属于闭包,他们都有权访问log_name变量。”read”负责读取log_name这个变量的值,而”write”负责重写log_name的值,在外部是没有任何情况直接访问log_name变量的,只能通过这两个方法来进行间接的访问和设置这个变量,这样的方法同样属于闭包。
var logHello;
logHello = ( function () {
var log_name = 'wyz';
return {
read: function () {
return log_name;
},
write: function (newValue) {
log_name = newValue;
}
};
} )();
闭包是怎么形成的?
从上面可以知道判断一个变量是否可以回收,根据这个变量的是否被引用就可以判断,比如下面例中,局部变量log_name被返回的匿名函数引用,那么就不会被垃圾回收器回收,这就是闭包的形成,因为闭包会保持对变量引用,让垃圾回收器不会回收此变量。
var logHello;
logHello = ( function () {
var log_num = 20;
return function() {
return log_num; <<返回一个匿名函数,函数内部可以对局部变量log_num进行访问。
};
} )();
经过上面的一些例子,就很容易理解了,噢~还没有理解?,那你再继续看看后面的总结吧(但相信我,多思考思考,肯定能理解)。
闭包可以理解为:会保存对变量的引用而不会让变量被垃圾回收器回收。
浅谈Javascript闭包的更多相关文章
- 浅谈JavaScript中的闭包
浅谈JavaScript中的闭包 在JavaScript中,闭包是指这样一个函数:它有权访问另一个函数作用域中的变量. 创建一个闭包的常用的方式:在一个函数内部创建另一个函数. 比如: functio ...
- 浅谈javascript函数节流
浅谈javascript函数节流 什么是函数节流? 函数节流简单的来说就是不想让该函数在很短的时间内连续被调用,比如我们最常见的是窗口缩放的时候,经常会执行一些其他的操作函数,比如发一个ajax请求等 ...
- [转载]浅谈JavaScript函数重载
原文地址:浅谈JavaScript函数重载 作者:ChessZhang 上个星期四下午,接到了网易的视频面试(前端实习生第二轮技术面试).面了一个多小时,自我感觉面试得很糟糕的,因为问到的很多问题都 ...
- 浅谈JavaScript浮点数及其运算
原文:浅谈JavaScript浮点数及其运算 JavaScript 只有一种数字类型 Number,而且在Javascript中所有的数字都是以IEEE-754标准格式表示的.浮点数的精度问题 ...
- 浅谈 JavaScript 编程语言的编码规范
对于熟悉 C/C++ 或 Java 语言的工程师来说,JavaScript 显得灵活,简单易懂,对代码的格式的要求也相对松散.很容易学习,并运用到自己的代码中.也正因为这样,JavaScript 的编 ...
- 浅谈javascript的原型及原型链
浅谈javascript的原型及原型链 这里,我们列出原型的几个概念,如下: prototype属性 [[prototype]] __proto__ prototype属性 只要创建了一个函数,就会为 ...
- 浅谈JavaScript中的null和undefined
浅谈JavaScript中的null和undefined null null是JavaScript中的关键字,表示一个特殊值,常用来描述"空值". 对null进行typeof类型运 ...
- 浅谈JavaScript中的正则表达式(适用初学者观看)
浅谈JavaScript中的正则表达式 1.什么是正则表达式(RegExp)? 官方定义: 正则表达式是一种特殊的字符串模式,用于匹配一组字符串,就好比用模具做产品,而正则就是这个模具,定义一种规则去 ...
- 浅谈JavaScript中的内存管理
一门语言的内存存储方式是我们学习他必须要了解的,接下来让我浅谈一下自己对他的认识. 首先说,JavaScript中的变量包含两种两种类型: 1)值类型或基本类型:undefined.null.numb ...
随机推荐
- 元数据标签Embed
关于Embed外部资源的使用方法总结 Flex软件中经常需要使用一些外部的资源,如图片.声音.SWF或字体,虽然你也可以在软件运行的时候引入和载入,但是也可能经常需要直接将这些资源编译(Compile ...
- 安装Laravel遇到You must enable the openssl extension to download files via https问题
刚看了一篇文章说了2014年最火的10个php框架,看到了Laravel,于是便自己试试,孰料刚安装便遇到了一个问题(由于一不小心关掉了cmd,此处无法截图显示),便是如文章标题中所说的那样,goog ...
- 解决位图失真-SetStretchBltMode()
当用以下函数加载一张位图时,当窗口发生重绘更改大小时,位图将失真: CBitmap bitmap; bitmap.LoadBitmap(IDB_BITMAP2); BITMAP bmp; bitm ...
- 小白日记28:kali渗透测试之Web渗透-扫描工具-Nikto
扫描工具-Nikto #WEB渗透 靶机:metasploitable 靶场:DVWA[默认账号/密码:admin/password] #新手先将DVWA的安全性,调到最低,可容易发现漏洞 侦察[减少 ...
- 小白日记13:kali渗透测试之服务扫描(三)-SMTB扫描、防火墙识别、负载均衡识别、WAF识别
SMTP扫描 SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式.SMTP协议属于TCP/ ...
- JavaFX(三)窗口拖动
1.问题场景 在上一篇中,我们将窗口的默认标题栏隐藏从而导致鼠标点击窗体无法进行拖动. 2.解决思路 给组件添加鼠标按下事件监听器和鼠标拖动事件监听器. 3.代码实现 代码片段: private do ...
- Android(java)学习笔记109:通过反射获取成员变量和成员方法并且使用
一.反射获取成员变量并且使用: 1.获取字节码文件对象: Class c = Class.forName("cn.itcast_01.Person"); 2.使用无 ...
- git 在windows上 生成ssh公钥
今天上传代码到服务器时,报如下错误: 上网搜了一下,应该是ssh过期了.我们就来生成新的ssh公钥吧. 1. 打开git bash 2. 输入命令: ssh-keygen -t rsa ...
- 远程管理之VNC
远程管理的基本概念 ①RDP(remote desktop protocol)协议 远程桌面协议,我们常用的windows操作系统就是的远程桌面管理就是基于该协议的,更多有关RDP协议的可以查看百度百 ...
- ACM一道关于素数查找的题
在ACM做这么一道题: 我用了最简单的查找素数的方法: bool isPrime(int n) { int t=n-1; while(t>2) { if(n%t==0) { return fal ...