资讯专栏INFORMATION COLUMN

JavaScript对内存的使用

Eastboat / 2789人阅读

摘要:内存图示意图内存图就是简化模拟示意使用的内存中的数据区中的情况,简单的分为栈内存堆内存,如下图。明显,左边是原始代码,中间是栈内存,右边是堆内存。如果原始代码中变量是对象,栈内存中就会存储堆内存的地址随机,堆内存中会存储这个对象的所有内容。

内存的分配(示意)

启动程序,就需要分配内存给运行的程序。启动浏览器,就会分配一定内存供浏览器使用,浏览器在会分配相应的内存供诸如HTML+CSS,JS,"HTTP","其他插件、定时器`等模块使用,如下图。

会有一部分内存供JS模块使用,JS一般会将JS代码存储在代码区,数据区内,通过某种联系将代码和数据对应在一起,如下图。

内存图 示意图

内存图就是简化模拟示意JS使用的内存中的数据区中的情况,简单的分为栈内存Stack,堆内存Heap,如下图。明显,左边是原始代码,中间是栈内存,右边是堆内存

使用

左边原始代码定义一个变量,在栈内存中就会用64位存储一个值。如果原始代码中变量是非对象栈内存中这个值就是直接值堆内存没有数据。如果原始代码中变量是对象栈内存中就会存储堆内存的地址(随机),堆内存中会存储这个对象的所有内容

看到上个图,原始代码区里最后一行O2=O,将一个对象赋值给另一个变量时,实际上是将堆内存的地址赋值给另一个变量,转换如下图,O2在栈内存中的内容就变成了和O一样的堆内存地址

应用实例 第一个

原始代码中定义变量a=1,Stack中存储1

原始代码中定义变量b=a,Stack中存储b的值和a一样,为1

原始代码中赋值b=2,都是非对象,Stack中直接将b的值改为2,不影响a

全程非对象,所以没有涉及堆内存Heap

第二个

原始代码中定义变量a={name:"a"},是个对象,随机分配Heap地址(比如:31)并在Heap中存储这个对象,在Stack中存储这个Heap地址,比如ADDR 31

原始代码中定义变量b=a,是个存在的对象,将a的Stack值(ADDR 31)(Heap地址)赋给b的Stack值

原始代码中赋值b=null,赋给了b一个非对象,将b的Stack值改为null,不影响a

全程操作Stack值,对象的Stack值为Heap地址

第三个

原始代码定义变量a={n:1},随机分配Heap地址(比如:34)并在Heap中存储这个对象,在Stack中存储这个Heap地址,比如ADDR 34

原始代码中定义变量b=a,是个存在的对象,将a的Stack值(ADDR 34)(Heap地址)赋给b的Stack值

a.x=a={n:2},这句话阅读顺序从左往右。首先,在Heap 34中添加新属性x:a,现在a的值是ADDR 34,所以新属性相当于x:ADDR 34。然后,把{n:2}赋值给a,因为是个新对象,所以重新分配Heap地址(ADDR 54),并把a的Stack值变更为新的Heap地址(ADDR 51)。

alert(a.x),现在a的值实际是ADDR 54ADDR 54里面是没有x这个属性的,所以返回undefined

alert(b.x),b一直是ADDR 34,其中x属性值为ADDR 54,所以是个对象,返回[object Object]

总之就是,原始代码里对对象的操作都在堆内存Heap中实现,对变量的操作都在栈内存Stack中实现。非对象的Stack值就是直接值,对象的Stack值是堆内存Heap的地址

第四个

原始代码中定义变量a={name:"a"},Heap中存储对象,Stack中存储Heap地址(ADDR 101)

原始代码b=a,把a的Stack值(Heap地址)赋给b的Stack值

原始代码b={"name":"b"},赋给b一个新对象,Heap中存储新对象,b的Stack值变更为新的Heap地址(ADDR 301)

所以,a.name没有变,还是a

第五个

原始代码中定义变量a={name:"a"},Heap中存储对象,Stack中存储Heap地址(ADDR 51)

原始代码b=a,把a的Stack值(Heap地址)赋给b的Stack值

原始代码设置b.name=b,就是ADDR 51中的name值变更为b

所以,a.name也就是ADDR 51中的name值,等于b

这里,a和b的Stack值都指向同一Heap地址ADDR 51,所以无论对那个进行操作,都是对一个东西做操作,所以会互相影响

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/107972.html

相关文章

  • 三个闭包实例理解闭包对内存的影响

    摘要:在试图弄清这个问题之前,先要理解栈内存堆内存和预处理。因此在子函数执行的时候,堆内存被占用了,相应的栈内存也将保留。所以,栈内存在执行完之后会被保留一段时间,这段时间等于其子函数执行的时间。 在试图弄清这个问题之前,先要理解栈内存、堆内存和预处理。 占用内存,不会销毁的闭包实例 例1: var num = 12; function fn() { var num = 100; ...

    jackzou 评论0 收藏0
  • JS中对内存的一些了解

    摘要:中对内存的一些了解在进行开发的过程中了解内存机制有助于开发人员能够清晰的认识到自己写的代码在执行的过程中发生过什么也能够提高项目的代码质量内存是怎么样的中变量存放有着原始值与引用值之分原始值原始的数据类型以及新加入的引用值等类型的值便是引用 JS中对内存的一些了解 在JS进行开发的过程中, 了解JS内存机制有助于开发人员能够清晰的认识到自己写的代码在执行的过程中发生过什么, 也能够提高...

    elliott_hu 评论0 收藏0
  • JavaScript 事件对内存和性能的影响

    摘要:事件对内存和性能的影响虽说事件处理程序可以为现代页面添加很强的交互能力,但是不分青红皂白就添加大量的事件处理程序绝对是一种愚蠢的行为。最适合采用事件委托的事件包括和。提交提交某个表单的操作代码移除事件处理程序提交中。。。 JavaScript 事件对内存和性能的影响 虽说事件处理程序可以为现代 Web 页面添加很强的交互能力,但是不分青红皂白就添加大量的事件处理程序绝对是一种愚蠢的行为...

    Ajian 评论0 收藏0
  • WebAssembly 系列(二)JavaScript Just-in-time (JIT) 工作原

    摘要:解释器的利弊解释器启动和执行的更快。正是因为这个原因,解释器看起来更加适合。这就是为什么最开始的浏览器都是用解释器的原因。可是当你运行同样的代码一次以上的时候,解释器的弊处就显现出来了。起初,监视器监视着所有通过解释器的代码。 作者:Lin Clark 编译:胡子大哈 翻译原文:http://huziketang.com/blog/posts/detail?postId=58c12f...

    Lin_R 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<