JS数据类型转换与内存模型

JS数据类型转换与内存模型
面试

  • JS数据类型转换
  • 拓展知识:内存与外存
  • 基础数据类型,对象,栈内存与堆内存
  • 一道经典(SB)面试题的内存分析
  • 垃圾回收与内存泄漏
  • 深拷贝与浅拷贝的概念

JS数据类型转换

一张图表示,简单明了~
算法

1

拓展:内存与外存

内存

内存分为RAM和ROM。RAM是随机存取存储器,用户可读可写,计算机断电后,存储在RAM的信息将被删除。RAM具体分为SRAM(Static RAM)和DRAM(Dynamic RAM)。咱们 如今所说的内存通常指的都是DRAM,SRAM速度更快,可是容量相对于其余类型内存而言也会小一些,而且价格也较为昂贵。通常SRAM做为CPU和DRAM之间的缓存(cache)。ROM是只读存储器,ROM的内容是制造商写进去的,用户只能读,但不能写。ROM在切断电源后,数据也不会丢失。计算机会给当前执行的程序动态地分配内存空间,例如用户打开浏览器打开诸多网页,计算机会给浏览器分配内存,浏览器会给每个页面分配内存,会给页面的HTML,CSS,JS分配内存。数组

外存

由于内存中的数据在断电以后会消失,因此为了数据的保存,就须要使用其余类型的存储器。这类存储器通常是磁盘,固态硬盘(ssd)等,也就是所谓的外存。浏览器

基础数据类型,对象,栈内存与堆内存

JS中的基础数据类型每每都保存在栈内存中,由于这些值都有固定的大小。
例如:var a = 1; 内存分配图大概是这个样子的:
缓存


JS中复杂数据类型即对象,例如数组,函数,因为它们的值大小非固定,因此它们的值实际上保存在堆内存当中。而栈内存中保存的是指向实际对象值的引用,这个引用咱们能够理解为一个地址。也就是说,在咱们操做对象时,实际上操做的是指向这个对象的引用,而并不是是实际的对象。
例如: var a = {'key':'value'}; 内存分配图大概是这个样子的:


一道经典(SB)面试题的内存分析

var a = {n:1};
var b = a;
a.x = a = {n:2};
=============================
问:
console.log(a.x)= ?
console.log(b.x) =?
复制代码

这道题涉及到了连续赋值的状况,在程序运行以后,先肯定好了a.x 和 a的引用,而后再从右往左开始赋值 。本题的内存分析以下:
bash

var a = {n:1};
var b = a;
复制代码

代码执行到这里时,内存图模型以下:
函数


在执行代码 a.x = a = {n:2};时,JS首先会肯定a在stack中的“地址”也就是指向对象的引用。

a.x = a = {n:2};
// 本例中a在stack中的地址为addr=31,在肯定好这个信息后,代码会从右至左开始执行。
复制代码

首先是a = {n:2}
ui


而后执行 a.x = a,在内存模型中,此时左边的a在stack中对应的地址为addr31,而右边的a在stack中的地址已经变为了addr33。因此这个操做至关于在addr31所指向的对象中添加x属性,x的属性值为addr33指向的对象。


因此结果以下:

垃圾回收与内存泄漏

参考内容:JavaScript内存管理一文。spa

JS内存的声明周期

  1. 内存分配:在声明变量,对象时,系统会对内存进行自动分配
  2. 内存使用:在读写内存时,也就是咱们在使用声明的变量,对象时,称为内存使用过程
  3. 内存回收:当一些数据被浏览器视做“垃圾”时,浏览器内部的GC回收机制会回收再也不使用的内存。

垃圾回收算法

引用计数算法

引用计数算法定义“垃圾”的标准很简单,就是看一个对象是否有指向它的引用,若是没有就回收。可是引用计数算法却存在着许多问题,试想若是在堆内存中,有对象相互引用,即使是它们再也不使用,可是GC不会进行回收,最后就会致使内存泄漏的问题,而IE6就是使用引用计数算法来进行垃圾回收的。
如代码:code

function c() {
    var o1 = {};
    var o2 = {};
    o1.a = o2;
    o2.a = o1; 
    
    return "IE6'Bug"
}

c();
复制代码

按理来说方法在调用以后,对象o1,o2能够进行回收了,可是在堆内存中二者互相引用,是根据引用计数算法的定义,在堆内存的这两个对象还存在着引用的关系,因此这部份内存不会被回收,接下来就有可能带来内存泄漏的问题。什么是内存泄漏呢?内存泄漏(Memory Leak) 是指在程序中动态被分配的堆内存中,因为某种缘由,致使程序未被释放或者说没法释放而形成了系统内存的浪费,进而致使程序运行速度减慢,甚至是系统崩溃。

标记清除算法

标记清除算法是现代浏览器主要使用,并在此之上加以改进并应用的算法,标记清除算法定义“垃圾”为从栈内存开始“没法达到”的对象。对于IE6出现的Bug,即使是堆内存中两个对象互相引用的状况,标记清除算法也能够进行回收。

深拷贝与浅拷贝的概念

如:

var a = 1;
var b = a;
复制代码

这个过程就是深拷贝,对于基本类型来讲,赋值的过程就是深拷贝。当咱们尝试去改变b的值时,变量a的值不会发生变化,换句话说,一个变不会影响另外一个这就是深拷贝。浅拷贝则偏偏相反,对于复杂类型而言:

var a = {name:'a'};
var b = a;
复制代码

a和b指向同一个对象,当改变a.name或b.name时,另外的引用指向的对象(其实就是本身)会发生改变,因此咱们能够这么理解:一个变会影响另外一个变这就是深拷贝。对于复杂类型来讲,也能够经过代码实现深拷贝,后续再见~

相关文章
相关标签/搜索