金色小芝麻

vuePress-theme-reco 金色小芝麻    2021 - 2023
金色小芝麻 金色小芝麻

Choose mode

  • dark
  • auto
  • light
主页
分类
  • JavaScript
  • BUG复盘
  • SVG笔记
  • TypeScript
  • 个人总结
  • CSS笔记
  • 开发工具
  • 前端入门
  • Vue2.0
  • 性能优化
  • 架构学习
  • 每日一题
标签
时间轴
社交
  • 掘金 (opens new window)
author-avatar

金色小芝麻

83

文章

27

标签

主页
分类
  • JavaScript
  • BUG复盘
  • SVG笔记
  • TypeScript
  • 个人总结
  • CSS笔记
  • 开发工具
  • 前端入门
  • Vue2.0
  • 性能优化
  • 架构学习
  • 每日一题
标签
时间轴
社交
  • 掘金 (opens new window)
  • 前端入门

    • 博客搭建过程及相关配置
    • 数组中的16种常用方法
    • JS中的数据类型简析——基本数据类型值
    • JS中的数据类型object基础
    • JS中三种常见的判断
    • 数据类型之间的区别(堆内存Heap VS 栈内存Stack)
    • JS基础练习题及解析
    • 开关灯的小案例
    • JS中数据类型检测方法——typeof
    • 条件判断几个小练习
    • JS循环——for循环
    • 自定义属性实现选项卡小案例
    • 字符串中的12种常用方法
    • DOM操作的简单原理
    • JS实现隔行变色鼠标跟随小案例
    • JS中function的基础知识
    • JS中数组去重的三种方法
    • JS中时间格式化的三种方法
    • JS中URL参数处理的三种方法
    • JS小案例——获取随机验证码
    • DOM操作之——获取DOM标签的9种方式
    • DOM操作之——DOM节点类型及属性
    • DOM操作之——元素的增删改、样式修改、插入内容
    • JS中THIS相关问题梳理
    • JS中的变量提升机制
    • 在全局:私有上下文中:带VAR和不带VAR的区别
    • 作用域和作用域链查找机制
    • JS中堆栈内存的释放问题
    • JS中的闭包机制
    • ES3和ES6定义变量的区别
    • JS中的单例和工厂设计模式
    • JS中的面向对象OOP理论基础
    • 构造函数创建自定义类
    • JS中的原型和原型链
    • Math中常用的9种方法
    • 从一道阿里经典面试题剖析函数三种角色
    • 重写内置call
    • 重写一个内置new
    • 浏览器渲染页面的主体流程
    • 减少DOM的回流和重绘
    • JS中的多种继承方式
    • JS中数据类型检测四种方式的优缺点
    • JS中的正则表达式&&全面梳理
    • 非严格模式 🆚 严格模式的区别
    • 数组方法reduce、filter、flat
    • 获取数组中最大值/最小值的三种基础方法
    • 轮播图——渐隐渐显版
    • 深克隆 VS 浅克隆|深比较 VS 浅比较|回调函数
    • 轮播图——左右切换版
    • 事件及事件绑定、事件对象及事件传播
    • 从在地址栏输入网址到看到页面的过程&&AJAX基础
    • 想自学JS吗?想提升JS底层原理吗?76张脑图带你彻底搞懂原生JS
    • 面试手写API系列
    • 30张脑图带你从零开始学VUE
    • JS中的盒子模型
    • 初识JS-基础中的基础
    • 前端发展简史
    • JS中的三大类输出方式

JS中堆栈内存的释放问题

vuePress-theme-reco 金色小芝麻    2021 - 2023

JS中堆栈内存的释放问题

金色小芝麻 2020-05-20

开辟的堆内存或者形成的上下文(进栈执行=>栈内存)是越多越好,还是越少越好?

  • 肯定是越少越好,因为计算机的内存是固定的,我们所有开辟的内存都在占用计算机的资源,当计算机内消耗存过多,性能也就越来越卡(直接导致我们的产品运行变慢)

# 思维导图

函数执行就会形成栈内存(从内存中分配的一块空间),如果内存都不销毁释放,很容易就会导致栈内存溢出(内存爆满,电脑就卡死了), => 所以JS中一个重要的性能优化点:减少内存的使用

  • =>释放堆内存
  • =>释放栈内存(也就是让进栈执行的上下文,尽可能出栈释放)

# 一、堆内存(HEAP)和 栈内存(STACK)

# 1、堆内存(HEAP)

  • 堆内存是用来存储引用数据类型值的
    • (例如:创建函数和创建对象,就是开辟一个堆内存,把代码字符串或者键值对存储到堆内存中的)

# 2、栈内存(STACK)

  • 栈内存是用来执行代码和存储基本类型值的(创建的变量也存栈里面了),
    • 不仅全局代码执行(EC(G)全局执行上下文),
    • 而且函数执行(EC(X)私有上下文),最后也都会进栈执行的
    • 基于ES6中的let/const形成的块作用域也是栈内存

# 二、浏览器常用的垃圾回收机制(内存释放机制):

# 1、 查找引用方式(weblit内核)

浏览器有自动回收垃圾的机制,定期间隔某段时间,把所有没有被占用的内存回收释放(这种垃圾回收机制,比其它语言要完善一些)

# -1).不会销毁的情况:

  • 创建一个堆(16进制地址):
    • 如果有变量或者其它东西存储了堆内存的地址,则当前堆内存被视为占用,也就不能释放销毁
  • 上下文进栈执行;
    • 如果当前上下文中的某些内容(一般也是当前上下文中创建的堆)被上下文以外的变量或者其它事务所占用,那么当前上下文就不能出栈释放(但是一般情况下,上下文中代码执行完,上下文自己就出栈释放了)

# -2).堆内存释放

如果堆内存用完后,我们想去手动释放它,则取消所有的占用:赋值为NULL(NULL是空对象指针,也就是不指向任何的堆内存)

//=>创建一个引用类型值,就会产生一个堆内存
//如果当前创建的堆内存不被其它东西所占用了(浏览器会在空闲的时候,查找每一个内存的引用状况,不被占用的都会给回收释放掉),则会释放
let obj = {
    name : 'xiaozhima'
};
let oop = obj;
//此时obj和oop都占用着对象的堆内存,想要释放堆内存,需要手动解除变量和值的关联(null:空对象指针)
obj = null;
oop = null;

# -3).栈内存释放

栈内存:

  • 打开浏览器形成的全局作用域是栈内存
  • 手动执行函数形成的私有作用域是栈内存
  • 基于ES6中的let/const形成的块作用域也是栈内存
  • ......

栈内存销毁:

  • 全局栈内存:关掉页面的时候才会销毁
  • 私有栈内存:
    • 1.一般情况下,函数只要执行完成,形成的私有栈内存就会被销毁释放掉(排除出现无限极递归、出现死循环的模式)
    • 2.但是一旦栈内存中的某个东西(一般都是堆地址)被私有作用域以外的事物给占用了,则当前私有栈内存不能立即被释放销毁(特点:私有作用域中的私有变量等信息也保留下来了=>这种函数执行形成不能被释放的私有栈内存,也叫做闭包)
function fn(){
    //...
}
fn(); //=>函数执行形成栈内存,执行完成栈内存销毁
     
function X(){
    return function(){
        //...
    }
}
let f=X(); //=>f占用了X执行形成的栈内存中的一个东西(返回小函数对应的堆),则X执行形成的栈内存不能被释放了

# 2、内存计数器方式(Trident内核)

当前内存被其它东西引用了,则给堆计数1(累加计数),取消占用后,则减1,当减到零之后,浏览器就可以把它释放了

# 三、练习题

# 1.输出结果

var i = 5;
function fn(i) {
	return function (n) {
		console.log(n + (++i));
	}
}
var f = fn(1);
f(2);
fn(3)(4);
fn(5)(6);
f(7);
console.log(i);

# 2.输出结果

let x = 5;
function fn(x) {
    return function(y) {
        console.log(y + (++x));
    }
}
let f = fn(6);
f(7);
fn(8)(9);
f(10);
console.log(x);

# 3.输出结果

let a=0,
    b=0;
function A(a){
    A=function(b){
        alert(a+b++);
    };
    alert(a++);
}
A(1);
A(2);

# 4.输出结果

var n=0; 
function a(){
    var n=10; 
    function b(){
        n++; 
        console.log(n); 
    }
    b();
    return b; 
}
var c=a();
c(); 
console.log(n);

# 5.输出结果

var test = (function(i){
    return function(){
        alert(i*=2);
    }
})(2);
test(5);

欢迎来到 金色小芝麻
看板娘