免费的图库网站,做网站jw100,十大购物软件,邢台163招聘最新信息一、 栈(stack)和 堆(heap)
栈(stack)#xff1a;是栈内存的简称#xff0c;栈是自动分配相对固定大小的内存空间#xff0c;并由系统自动释放#xff0c;栈数据结构遵循FILO#xff08;first in last out#xff09;先进后出的原则#xff0c;较为经典的就是乒乓球盒结…一、 栈(stack)和 堆(heap)
栈(stack)是栈内存的简称栈是自动分配相对固定大小的内存空间并由系统自动释放栈数据结构遵循FILOfirst in last out先进后出的原则较为经典的就是乒乓球盒结构先放进去的乒乓球只能最后取出来。 堆(heap)是堆内存的简称堆是动态分配内存内存大小不固定也不会自动释放堆数据结构是一种无序的树状结构同时它还满足key-value键值对的存储方式我们只用知道key名就能通过key查找到对应的value。比较经典的就是书架存书的例子我们知道书名就可以找到对应的书籍。 栈的特点开口向上、速度快,容量小堆的特点速度稍慢、容量比较大
二、 基本类型和引用类型 基本数据类型Undefined,String,Boolean,Null,Number都是直接按值存放在栈内存中占用的内存空间的大小是确定的并由系统自动分配和自动释放。这样带来的好处就是内存可以及时得到回收相对于堆来说更加容易管理内存空间。 引用数据类型指那些可能由多个值构成的对象如对象(Object)、数组(Array)、函数(Function) 它们是通过拷贝和new出来的这样的数据存储于堆中。
三、 传值和传址的区别
基本类型采用的是值传递。 引用类型则是地址传递。
引用类型的数据的地址指针是存储于栈中的将存放在栈内存中的地址赋值给接收的变量。当我们想要访问引用类型的值的时候需要先从栈中获得对象的地址指针然后在通过地址指针找到堆中的所需要的数据保存在堆内存中,包含引用类型的变量实际上保存的不是变量本身而是指向该对象的指针。
四、 内存分配垃圾回收
1.内存分配 1栈内存线性有序存储容量小系统分配效率高。 2堆内存首先要在堆内存新分配存储区域之后又要把指针存储到栈内存中效率相对就要低一些了。
2.垃圾回收 1栈内存变量基本上用完就回收了相比于堆来说存取速度会快并且栈内存中的数据是可以共享的。 2堆内存堆内存中的对象不会随方法的结束而销毁就算方法结束了这个对象也可能会被其他引用变量所引用(参数传递)。创建对象是为了反复利用因为对象的创建成本通常较大这个对象将被保存到运行时数据区也就是堆内存。只有当一个对象没有任何引用变量引用它时系统的垃圾回收机制才会在核实的时候回收它。
五、浏览器垃圾回收机制
1. 浏览器的垃圾回收机制
(1). 垃圾回收的概念 垃圾回收JavaScript代码运⾏时需要分配内存空间来储存变量和值。当变量不在参与运⾏时就需要系统收回被占⽤的内存空间这就是垃圾回收。
回收机制 ● Javascript 具有⾃动垃圾回收机制会定期对那些不再使⽤的变量、对象所占⽤的内存进⾏释放原理就是找到不再使⽤的变量然后释放掉其占⽤的内存。 ● JavaScript中存在两种变量局部变量和全局变量。全局变量的⽣命周期会持续要⻚⾯卸载⽽局部变量声明在函数中它的⽣命周期从函数执⾏开始直到函数执⾏结束在这个过程中局部变量会在堆或栈中存储它们的值当函数执⾏结束后这些局部变量不再被使⽤它们所占有的空间就会被释放。 ● 不过当局部变量被外部函数使⽤时其中⼀种情况就是闭包在函数执⾏结束后函数外部的变量依然指向函数内部的局部变量此时局部变量依然在被使⽤所以不会回收。
(3) 垃圾回收的⽅式 浏览器通常使⽤的垃圾回收⽅法有两种标记清除引⽤计数。 (1标记清除
● 标记清除是浏览器常⻅的垃圾回收⽅式当变量进⼊执⾏环境时就标记这个变量“进⼊环境”被标记为“进⼊环境”的变量是不能被回收的因为他们正在被使⽤。当变量离开环境时就会被标记为“离开环境”被标记为“离开环境”的变量会被内存释放。
● 垃圾收集器在运⾏的时候会给存储在内存中的所有变量都加上标记。然后它会去掉环境中的变量以及被环境中的变量引⽤的标记。⽽在此之后再被加上标记的变量将被视为准备删除的变量原因是环境中的变量已经⽆法访问到这些变量了。最后。垃圾收集器完成内存清除⼯作销毁那些带标记的值并回收他们所占⽤的内存空间。 (2引⽤计数 ● 另外⼀种垃圾回收机制就是引⽤计数这个⽤的相对较少。引⽤计数就是跟踪记录每个值被引⽤的次数。当声明了⼀个变量并将⼀个引⽤类型赋值给该变量时则这个值的引⽤次数就是1。相反如果包含对这个值引⽤的变量⼜取得了另外⼀个值则这个值的引⽤次数就减1。当这个引⽤次数变为0时说明这个变量已经没有价值因此在在机回收期下次再运⾏时这个变量所占有的内存空间就会被释放出来。
● 这种⽅法会引起循环引⽤的问题例如 obj1 和 obj2 通过属性进⾏相互引⽤两个对象的引⽤次数都是2。当使⽤循环计数时由于函数执⾏完后两个对象都离开作⽤域函数执⾏结束obj1 和 obj2 还将会继续存在因此它们的引⽤次数永远不会是0就会引起循环引⽤。
function fun() {let obj1 {}let obj2 {}obj1.a obj2 // obj1 引用了 obj2obj2.a obj1 // obj2 引用了 obj1
}这种情况下就要⼿动释放变量占⽤的内存
obj1.a null
obj2.a null(3) 减少垃圾回收 虽然浏览器可以进⾏垃圾⾃动回收但是当代码⽐较复杂时垃圾回收所带来的代价⽐较⼤所以应该尽量减少垃圾回收。 ● 对数组进⾏优化在清空⼀个数组时最简单的⽅法就是给其赋值为[ ]但是与此同时会创建⼀个新的空对象可以将数组的⻓度设置为0以此来达到清空数组的⽬的。 ● 对 object 进⾏优化对象尽量复⽤对于不再使⽤的对象就将其设置为null尽快被回收。 ● 对函数进⾏优化在循环中的函数表达式如果可以复⽤尽量放在函数的外⾯。
2. 哪些情况会导致内存泄漏
以下四种情况会造成内存的泄漏 ● 意外的全局变量由于使⽤未声明的变量⽽意外的创建了⼀个全局变量⽽使这个变量⼀直留在内存中⽆法被回收。 ● 被遗忘的计时器或回调函数设置了 setInterval 定时器⽽忘记取消它如果循环函数有对外部变量的引⽤的话那么这个变量会被⼀直留在内存中⽽⽆法被回收。 ● 脱离 DOM 的引⽤获取⼀个 DOM 元素的引⽤⽽后⾯这个元素被删除由于⼀直保留了对这个元素的引⽤所以它也⽆法被回收。 ● 闭包不合理的使⽤闭包从⽽导致某些变量⼀直被留在内存当中。