JS高级——内存管理和闭包

0、预备知识

0.1 认识内存管理

不管什么样的编程语言,在代码的执行过程中都是需要给它分配内存的,不同的是某些编程语言需要我们自己手动的管理内存,某些编程语言会可以自动帮助我们管理内存:

不管以什么样的方式来管理内存,内存的管理都会有如下的生命周期:

  • 第一步:分配申请你需要的内存(申请);
  • 第二步:使用分配的内存(存放一些东西,比如对象等);
  • 第三步:不需要使用时,对其进行释放;

不同的编程语言对于第一步和第三步会有不同的实现:

  • 手动管理内存:比如C、C++,包括早期的OC,都是需要手动来管理内存的申请和释放的(malloc和free函数);
  • 自动管理内存:比如Java、JavaScript、Python、Swift、Dart等,它们有自动帮助我们管理内存;

我们可以知道JavaScript通常情况下是不需要手动来管理的。

0.2 JS的内存管理

JavaScript会在定义变量时为我们分配内存。但是内存分配方式是一样的吗?

  • JS对于基本数据类型内存的分配会在执行时,直接在栈空间进行分配;
  • JS对于复杂数据类型内存的分配会在堆内存中开辟一块空间,并且将这块空间的指针返回值变量引用;
    在这里插入图片描述

0.3 JS的垃圾回收

因为内存的大小是有限的,所以当内存不再需要的时候,我们需要对其进行释放,以便腾出更多的内存空间。

在手动管理内存的语言中,我们需要通过一些方式自己来释放不再需要的内存,比如free函数:

  • 但是这种管理的方式其实非常的低效,影响我们编写逻辑的代码的效率;
  • 并且这种方式对开发者的要求也很高,并且一不小心就会产生内存泄露;

所以大部分现代的编程语言都是有自己的垃圾回收机制:

  • 垃圾回收的英文是Garbage Collection,简称GC;
  • 对于那些不再使用的对象,我们都称之为是垃圾,它需要被回收,以释放更多的内存空间;
  • 而我们的语言运行环境,比如Java的运行环境JVM,JavaScript的运行环境js引擎都会内存 垃圾回收器;
  • 垃圾回收器我们也会简称为GC,所以在很多地方你看到GC其实指的是垃圾回收器;

但是这里又出现了另外一个很关键的问题:GC怎么知道哪些对象是不再使用的呢?

  • 这里就要用到GC的算法了

0.3.1 常见的GC算法 – 引用计数

引用计数:

  • 当一个对象有一个引用指向它时,那么这个对象的引用就+1,当一个对象的引用为0时,这个对象就可以被销毁掉;
  • 这个算法有一个很大的弊端就是会产生循环引用,比如如下:循环引用的两个obj无法被GC回收
    在这里插入图片描述

0.3.2 常见的GC算法 – 标记清除

标记清除:

  • 这个算法是设置一个根对象(root object)(在浏览器中,这个根对象就是全局对象GO),垃圾回收器会定期从这个根开始,找所有从根开始有引用到的对象,对于哪些没有引用到的对象,就认为是不可用的对象;
  • 这个算法可以很好的解决循环引用的问题;
    在这里插入图片描述
    JS引擎比较广泛的采用的就是标记清除算法,当然类似于V8引擎为了进行更好的优化,它在算法的实现细节上也会结合一些其他的算法。

一、JS中闭包的定义

  • 一个普通的函数function,如果它可以访问外层作用于的自由变量,那么这个函数就是一个闭包;
  • 从广义的角度来说:JavaScript中的函数都是闭包;
  • 从狭义的角度来说:JavaScript中一个函数,如果访问了外层作用于的变量,那么它是一个闭包;

二、闭包的访问过程(内存图)

如果我们编写了如下的代码,它一定是形成了闭包的:
在这里插入图片描述

2.1 创建GO对象,创建全局执行上下文并压入执行上下文栈中

在这里插入图片描述

2.2 执行foo(),创建foo函数的AO对象

在这里插入图片描述

2.3 创建foo函数执行上下文并压入执行上下文栈中,然后开始执行foo函数内的代码

在这里插入图片描述

2.4 foo函数执行结束,将foo函数执行上下文弹出栈

在这里插入图片描述

2.5 执行fn()函数,创建fn函数(bar)的AO对象,创建fn函数(bar)的函数执行上下文并压入执行上下文栈中

在这里插入图片描述

2.6 fn函数(bar)执行完成,将fn函数(bar)的函数执行上下文弹出栈,垃圾回收器销毁bar函数的AO对象

在这里插入图片描述

注意:在此之前,是存在内存泄漏的,因为foo函数执行结束了,但是foo函数的AO对象并没有被销毁(因为有bar函数对象指向它)。foo函数的AO对象是应该被销毁的但没被销毁,所以说存在内存泄露!

2.7 执行fn = null,由于fn变量指向null,bar函数的AO对象没有任何变量指向,所以垃圾回收器会销毁bar函数的AO对象

在这里插入图片描述

2.8 由于bar函数的AO对象被垃圾回收器销毁,foo函数的AO对象没有任何变量指向,也会被垃圾回收器销毁

在这里插入图片描述

2.9 指向foo = null,foo变量指向null,不再指向foo函数对象

在这里插入图片描述

2.10 由于foo函数对象没有任何变量指向,所以会被垃圾回收器销毁

在这里插入图片描述

三、AO不使用的属性

我们来研究一个问题:AO对象不会被销毁时,是否里面的所有属性都不会被释放?

  • 下面这段代码中name属于闭包的父作用域里面的变量;
  • 我们知道形成闭包之后count一定不会被销毁掉,那么name是否会被销毁掉呢?
  • 这里我打上了断点,我们可以在浏览器上看看结果;
    在这里插入图片描述

答案:AO不使用的属性name是会被销毁的

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/470103.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

提取多个字段_【博客翻译】建筑物轮廓线提取以及损坏分类

原文链接原作者:Rohit Singh, Sandeep Kumar贡献者:Vinay Viswambharan, Divyansh Jha, Shivani Pathak, Daniel Wilson.翻译:荆雪涵在今年的 Esri 用户大会上,USAA 展示了基于 ArcGIS 深度学习能力,对 Woolsey 火灾进…

读取外部配置文件_SpringBoot外部配置、优先级及配置详解

一、外部配置及优先级SpringBoot的外部配置属性值官方给出了很多种方式,以便可以在不同的环境中使用相同的代码。其使用了非常特别的PropertySource命令,旨在允许合理的覆盖值。当然,如果属性值不同,则这些配置方式中的属性值都会…

Jquery 禁用浏览器的 后退和前进按钮

使用js,Jquery 禁用浏览器的back 和 next 按钮: 有时为了防治用户乱了访问顺序,不得不禁掉浏览器的前进后退按钮。 jQuery(document).ready(function () {if (window.history && window.history.pushState) {$(window).on(popstate, function ()…

JS数据结构与算法——冒泡排序(把大的数字依次往后放)

一、图解排序过程 注意:比较次数和交换次数之所以不一致,是因为:比较了并不一定就需要交换两个数字的位置,比如比较 1 和 2两个数字,由于 后者本身就比前者大,所以不需要交换两者的位置。 二、代码实现 三…

手机长曝光怎么设置_摄影教程丨手机如何拍摄长曝光照片,流光快门,星空银河搞起来!...

微信搜一搜定格取景框长曝光摄影可以拍摄出一些很酷的照片。这是一种非常灵活的摄影技术。它可以用来拍摄城市夜景,记录光绘,也可以拍摄水景片。甚至可以拍摄银河或捕捉星轨。其实长曝光不仅仅适合专业摄影师!任何人都可以用手机进行慢门拍摄…

JS数据结构与算法——选择排序(把小的数字依次往前放)

一、图解排序过程 注意&#xff1a;选择排序一样是需要进行两两的比较&#xff0c;但比较过程中不进行交换&#xff0c;只有比较完成后&#xff0c;找到最小的那个数&#xff0c;才会进行交换&#xff0c;把它放到最前面。 二、代码实现 三、完整代码 <!DOCTYPE html> &…

插入模板_WordPress在文章列表和内容页插入广告

本文已同步到专业技术网站 www.sufaith.com, 该网站专注于前后端开发技术与经验分享, 包含Web开发、Nodejs、Python、Linux、IT资讯等板块.一、在文章列表插入广告文章列表模板 包括以下几个类型以及对应的主体文件:首页模板 (index.php)搜索结果页 (search.php)文章归档 (arch…

JS数据结构与算法——插入排序

一、图解排序过程 二、代码实现 三、完整代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title> </head> <body><script>// 创建列表类function ArrayList() {//…

cad完全卸载教程_CAD室内设计中厨房布置实例

▲ 点击“CAD教学”&#xff0c;获取海量学习资料和免费教程本文介绍CAD室内设计中厨房布置方法&#xff1a;1、如下图是把另一边墙砌好&#xff0c;因为不砌的话门太大的话不好。在煮菜的烟容易在烟到不胜客厅里。2、在用矩形画宽为40长为800的玻璃门。3、在把厨房的台画出来&…

CSS布局(圣杯布局、双飞翼布局、水平垂直居中)

一、圣杯布局 要求&#xff1a;三列布局&#xff1b;中间主体内容前置&#xff0c;且宽度自适应&#xff1b;两边内容定宽 好处&#xff1a;重要的内容放在文档流前面可以优先渲染 原理&#xff1a;利用相对定位、浮动、负边距布局&#xff0c;而不添加额外标签 <!DOCTYPE …

cad怎么设置线的粗细_CAD软件中怎么设置CAD线宽?

在使用CAD软件绘制CAD图纸的过程中&#xff0c;不同线宽的用处是不同的。在机械制图中&#xff0c;零部件的外轮廓就是用粗实线&#xff0c;图形内部的剖开线使用细实线。一般情况下&#xff0c;都是在绘制图形过程中先设置好图形的线宽对象&#xff0c;但也有些需要在后面的绘…

检测范围_论文检测系统的检测范围有哪些

为了能够让研究人员&#xff0c;甚至一些专业的学术专家在进行论文创作的时候&#xff0c;端正自己的学术态度&#xff0c;很多人都会要求他们在提交甚至是发表论文之前&#xff0c;附上自己的查重证明&#xff0c;只有查重率低于一定程度时&#xff0c;提交的论文才是合格的。…

2学习率调整_学习率衰减

之前我们的优化&#xff0c;主要是聚焦于对梯度下降运动方向的调整&#xff0c;而在参数迭代更新的过程中&#xff0c;除了梯度&#xff0c;还有一个重要的参数是学习率α&#xff0c;对于学习率的调整也是优化的一个重要方面。01—学习率衰减首先我们以一个例子&#xff0c;来…

mysql 用户管理表_Mysql—用户表详解(mysql.user)

MySQL数据库Mysql—用户表详解(mysql.user)MySQL是一个多用户管理的数据库&#xff0c;可以为不同用户分配不同的权限&#xff0c;分为root用户和普通用户&#xff0c;root用户为超级管理员&#xff0c;拥有所有权限&#xff0c;而普通用户拥有指定的权限。MySQL是通过权限表来…

Orchard商城模块(Commerce)设计与后台部分

前言&#xff1a;使用CMS开发网站为目标&#xff0c;编写一个扩展性比较好的商城模块。 首先是整体流程图&#xff0c;大概介绍功能与设计。 接下来我们逐个模块功能介绍。 一。商品管理模块 商品模块中可发布需要在线售卖的商品 (套餐商品) 1.1 添加一个商品 1. 商品正常价&…

mysql数据库架构_MySQL数据库之互联网常用架构方案

一、数据库架构原则高可用高性能可扩展一致性二、常见的架构方案方案一&#xff1a;主备架构&#xff0c;只有主库提供读写服务&#xff0c;备库冗余作故障转移用jdbc:mysql://vip:3306/xxdb高可用分析&#xff1a;高可用&#xff0c;主库挂了&#xff0c;keepalive(只是一种工…

laravel方法汇总详解

1.whereRaw() 用原生的SQL语句来查询&#xff0c;whereRaw(select * from user) 就和 User::all()方法是一样的效果 2.whereBetween() 查询时间格式 whereBetween(problem_date, [2016-10-05 19:00:00, 2016-10-05 20:35:10]) 这种可以查到&#xff0c;时间格式类似这种, 查询日…

输入输出优化

被各种变态的出题者出的数据坑到了这里/sad 1 int read() 2 { 3 int num0; char chgetchar(); 4 while(ch<0&&ch>9) chgetchar(); //过滤前面非数字字符 5 while(ch>0&&ch<9) {num*10;numch-0;chgetchar();} 6 return num…

mysql整数索引没用到_MYSQL 索引无效和索引有效的详细介绍

1、WHERE字句的查询条件里有不等于号(WHERE column!...)&#xff0c;MYSQL将无法使用索引2、类似地&#xff0c;如果WHERE字句的查询条件里使用了函数(如&#xff1a;WHERE DAY(column)...)&#xff0c;MYSQL将无法使用索引3、在JOIN操作中(需要从多个数据表提取数据时)&#x…

如何参与一个GitHub开源项目

Github作为开源项目的著名托管地&#xff0c;可谓无人不知&#xff0c;越来越多的个人和公司纷纷加入到Github的大家族里来&#xff0c;为开源尽一份绵薄之力。对于个人来讲&#xff0c;你把自己的项目托管到Github上并不表示你参与了Github开源项目&#xff0c;只能说你开源了…