摘要:我的理解就是还处于被引用状态。内存机制的内存空间分为栈堆其中栈存放变量,堆存放复杂对象。对堆内数据进行复制修改时理解闭包有了前面的铺垫,我们再来看看闭包是怎么回事。这种反常的现象我们就叫它,中文名闭包。这就是闭包形成的原因了。
知识小储备
ECMAScript 的数据有两种类型:基本类型值和引用类型值,基本类型指的是简单的数据段,引用类型指的是可能由多个值构成的对象。垃圾回收Undefined、Null、Boolean、Number 和 String 是值类型,其他都是引用类型。
我们创建的原始类型、对象、函数等等,都会占用内存。为了防止溢出,我们就需要对不用的数据进行删除。这就是垃圾回收。
可触及(Reachability)JavaScript 内存管理的关键概念是可触及(Reachability)。
我的理解就是还处于被引用状态。
将全局(无论是window还是global)比作树根,我们创建的原始类型、对象、函数等等比作一个个枝杈。如果可以从window不断层的知道某个变量,那这个变量就是可触及的,不可回收的。
举个例子:
// user has a reference to the object let user = { name: "John" };
箭头代表的是对象引用。全局变量 "user" 引用了对象{name: "John"}(简称此对象为 John)。John 的 "name" 属性储存的是一个原始值,所以无其他引用。
如果覆盖 user,对 John 的引用就丢失了:
user = null;
现在 John 变得不可触及,垃圾回收机制会将其删除并释放内存。
内存机制js的内存空间分为栈 (stack)、堆 (heap);其中栈存放变量,堆存放复杂对象。
借用一张图直观感受一下
只能存放基本数据类型的数据和对象类型的引用地址也叫哈希码。里面的数据后进先出。
对栈内数据进行复制修改时:
是用来存储 “数组类型” 和“对象类”的数据。特点是存储空间大。
对堆内数据进行复制修改时:
有了前面的铺垫,我们再来看看闭包是怎么回事。还是举个例子:
//决策层开会决定生产新一代phone手机,就弄了个叫PhoneFactory的企划案 let Proposal = function(){ //新一代手机信息被封装在企划案中 let version = "XX", money = 10000 return function (){ //生产新的手机 return { version: version, money: money } } } //执行者根据策划案建成了一个工厂, 工厂方法每执行一次就产出一个手机 let Factory = new Proposal(); let phone1 = Factory(); console.log(phone1.version)
对于手机的version, money而言, 它是策划书Proposal的内部变量,而Proposal的同级phone1应该是访问不到。但实际上我们还是拿到了手机的版本和价格数据。这种反常的现象我们就叫它Closure,中文名闭包。
原因我们不管它为什么叫这个名字,先看看具体是什么原因产生的。
根据上面说的垃圾回收机制。函数Proposal在执行过之后(第16行)就没有引用。那么Proposal久应该被回收。里面的所有内部变量也应该被回收了。
但实际上 Proposal返回了一个新的函数Factory。而这个Factory是要能够访问到它生成时的同级以及父祖辈变量。而Proposal内部变量version, money就有了新的引用。因而阻止了被回收。就像Factory生成了一个新的泡泡把它能访问到的作用域包裹了起来。这就是闭包形成的原因了。
基于上面的js内存机制的知识,我们可以画出下面这张图:
图简陋了点。。。。
但也可以看出,对于变量version,money而言。虽然他们本身在proposal的黄色作用域中。但也在fatory生成的时候也被包含在了fatory打的可访问的作用域气泡内。不仅他们,甚至更外层的也都被包含在内。
在proposal这个泡泡破碎之后,只有当打的红色泡泡也破了,这些变量才会真的被回收。这也是为什么闭包用多了会影响性能的原因。
前端基础进阶:详细图解 JavaScript 内存空间
垃圾回收
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/96310.html
摘要:如何在初学就理解闭包你需要接着读下去。这样定义闭包是函数和声明该函数的词法环境的组合。小结闭包在中随处可见。闭包是中的精华部分,理解它需要具备一定的作用域执行栈的知识。 这是本系列的第 4 篇文章。 作为 JS 初学者,第一次接触闭包的概念是因为写出了类似下面的代码: for (var i = 0; i < helpText.length; i++) { var item = he...
摘要:当初看这个解释有点懵逼,理解成闭包就是函数中的函数了。里的闭包最近不满足于只干前端的活,开始用起了。里的闭包最近在学习语言,让我们来看一下语言里的闭包。在中,闭包特指将函数作为值返回的情况,被返回的函数引用了生成它的母函数中的变量。 本人开始接触编程是从js开始的,当时网上很多人说闭包是难点,各种地方对闭包的解释也是千奇百怪。如今开始接触js以外的各种编程语言,发现不光是js,php、...
摘要:当初看这个解释有点懵逼,理解成闭包就是函数中的函数了。里的闭包最近不满足于只干前端的活,开始用起了。里的闭包最近在学习语言,让我们来看一下语言里的闭包。在中,闭包特指将函数作为值返回的情况,被返回的函数引用了生成它的母函数中的变量。 本人开始接触编程是从js开始的,当时网上很多人说闭包是难点,各种地方对闭包的解释也是千奇百怪。如今开始接触js以外的各种编程语言,发现不光是js,php、...
摘要:闭包在我理解是一种比较抽象的东西。所以我写了一篇博文来方便自己理解闭包。那么现在我们可以解释一下闭包的第一个定义在计算机科学中,闭包是引用了自由变量的函数。循环中创建闭包在我们使用的关键字之前,闭包的一个常见问题就出现在循环中创建闭包。 零. 前言 从我开始接触前端时就听说过闭包,但是一直不理解闭包究竟是什么。上网看了各种博客,大家对闭包的说法不一。闭包在我理解是一种比较抽象的东西。所...
摘要:但是闭包也不是什么复杂到不可理解的东西,简而言之,闭包就是闭包就是函数的局部变量集合,只是这些局部变量在函数返回后会继续存在。可惜的是,并没有提供相关的成员和方法来访问闭包中的局部变量。 (收藏自 技术狂) 前言:还是一篇入门文章。Javascript中有几个非常重要的语言特性——对象、原型继承、闭包。其中闭包 对于那些使用传统静态语言C/C++的程序员来说是一个新的语言特性。本文将...
阅读 3768·2021-08-30 09:47
阅读 3690·2019-08-30 15:56
阅读 677·2019-08-30 14:18
阅读 698·2019-08-29 16:17
阅读 2065·2019-08-29 11:07
阅读 641·2019-08-26 13:53
阅读 3443·2019-08-26 10:26
阅读 2491·2019-08-23 18:30