一个热爱技术的菜鸟...用点滴的积累铸就明日的达人

正文
  如果真的想学好一门语言,那么一定要了解它内存模型,本篇文章就带你走进JavaScript的内存模型,由于本人才疏学浅,若有什么表述有误的地方,欢迎各位看官能够指点一二,在此不胜感激...
  在阅读这边文章之前,默认您已经掌握了JavaScript的基本概念、栈堆等基本数据结构以及计算机基本理论基础,如有了解欠缺,请移步相关博客后再阅读本文。
一、基本的数据类型的内存结构
  首先粗略的介绍一下JavaScript中五种基本的数据类型Undefined、Null、Boolean、Number、String;其中对于Undefined与Null的区别,网上有很多大牛都有介绍,在此本文暂不涉及,如有疑虑之处,请移步相关博客。或许有看官会问为什么在介绍JavaScript内存模型之前要先介绍JavaScript的基本数据类型的内存结构呢?这是因为JavaScript内存模型与基本数据类型的内存结构的关系就好比数学与实数的关系,基本数据类型的内存结构是整个JavaScript内存模型的基础。那么接下来就让我以最简短的方式来阐述一下基本数据类型的内存结构吧~
  基本数据类型的内存结构:在JavaScript中基本的数据类型都是以值的形式保存在内存中的。举个例子:

var inta = 10;
var strb = 'Hello';

  那么在执行完这段JavaScript代码之后,内存中会有两个区域分别表示为inta,strb;其中表示inta区域的值为‘10’,表示strb区域的值为‘Hello’,也即表示inta与strb的内存区域保存的均为实际的真值;

二、引用数据类型的内存结构

  在JavaScript中除了基本数据类型,那就剩下引用数据类型了,所以在介绍玩基本数据类型内存结构之后,就很有必要再介绍一下引用数据类型内存结构。引用数据类型的真实对象是保存在堆内存中的,而JavaScript与Java相似,均不可以直接访问堆内存,所以都是使用“引用”这个东西来访问处于堆中的对象,引用与对象的关系可以描述成遥控器与电视机之间的关系,我们可以持有遥控器来操控电视机。所谓的引用其实就是一块内存的地址,即在表示引用的区域上保存的是内存中对象的内存地址值,如图所示:

  其中假设对象处于内存中一个位置叫做0x23215的区域,那么椭圆的区域表示这个对象的引用,椭圆区域中存的就是0x23125这个值,在实际的操作中执行环境会通过引用中存的0x23125,去找到内存中的这个对象。

三、内存模型

  在JavaScript执行时期,可以将内存从逻辑上划分为两部分:栈与堆。其中栈是在JavaScript执行时,用于储存执行上下文(后续文章会介绍)的,而堆是存储对象的区域。在执行上下文生成之后,会创建一个变量对象(后续文章会介绍),变量对象是一个特殊的对象,它也会存储在堆。基本数据类型往往都会直接保存在变量对象中,而引用数据类型实际上是在变量对象中保存一个引用指向对象的地址(也即引用本身)。

  学习完JavaScript中的内存模型之后,请各位看官看看下面这段代码,并且猜猜它的输出结果,以验证上述知识的理解程度:

var inta = 10;
var stra = 'Hello'; var obja = {a: 10, b: 'Hello'}; var intb = inta;
var strb = stra;
var objb = obja; intb = 20;
strb = 'World';
objb.a = 20;
objb.b = 'World'; console.log(inta, intb);
console.log(stra, strb);
console.log(obja, objb);

  运行结果:

10 20
Hello World
{ a: 20, b: 'World' } { a: 20, b: 'World' }

  这其中会涉及到对象的赋值问题,在对基本数据类型赋值的时候,都是将原值赋值到新的对象上,所以改变新的对象的值,并不会影响到原值(因为它们本质上保存的是两个值);而对引用数据类型赋值则是将引用所指向对象的地址赋值给另一个引用,而在后续操作中,如果通过新的引用去改变对象中内部的值的话,还是会影响原来的引用所指向的对象(因为它们本质上保存的是同一个对象)

四、内存回收机制

  JavaScript具有自动的垃圾回收机制,也即执行环境会负责代码的执行过程中使用的内存,它会定期(周期性)找出哪些不再使用的对象,然后释放其内存。目前JavaScript最常用的垃圾回收算法为标记清除算法,垃圾回收机制会通过标记的算法来决定哪些对象是不需要再次使用的,然后再进行清除,也即清理哪些被定义为垃圾的JavaScript对象。

  上述所述的不再使用的变量也就是生命周期结束的变量,当然只可能是局部变量。全局变量的生命周期直到浏览器卸载页面才会结束,所以声明一个全局变量的时候,我们一定要慎重的考虑,在使用完这个变量的对象之后,我们是否还在需要这个对象,如果不需要的话,我们应该手动的将这个变量置为空,这样在下一次垃圾回收的时候,就能去释放这个变量上一次指向的对象(请注意变量与对象的区别)。

  下面请各位看官see一下以下的代码,来分析一下垃圾回收。

function fun1() {
var obj = {name: 'csa', age: 24};
} function fun2() {
var obj = {name: 'coder', age: 2}
return obj;
} var f1 = fun1();
var f2 = fun2();

  在上述代码中,当执行var f1 = fun1();的时候,执行环境会创建一个{name:'csa', age:24}这个对象,当执行var f2 = fun2();的时候,执行环境会创建一个{name:'coder', age=2}这个对象,然后在下一次垃圾回收来临的时候,会释放{name:'csa', age:24}这个对象的内存,但并不会释放{name:'coder', age:2}这个对象的内存。这就是因为在fun2()函数中将{name:'coder, age:2'}这个对象返回,并且将其引用赋值给了f2变量,又由于f2这个对象属于全局变量,所以在页面没有卸载的情况下,f2所指向的对象{name:'coder', age:2}是不会被回收的。

  由于JavaScript语言的特殊性(闭包...),导致如何判断一个对象是否会被回收的问题上变的异常艰难,这不仅需要我们有很强的基本功,还需要在以后的项目中积累经验。最后顺便说一句,即使随着硬件的更新换代以及垃圾回收机制的改进,我们也不应该忽视垃圾回收的基本理论,因为这是提高代码性能的关键一步,只有这样我们才能写出那些堪称艺术品的代码...

JavaScript学习系列之内存模型篇的更多相关文章

  1. JVM学习笔记——内存模型篇

    JVM学习笔记--内存模型篇 在本系列内容中我们会对JVM做一个系统的学习,本片将会介绍JVM的内存模型部分 我们会分为以下几部分进行介绍: 内存模型 乐观锁与悲观锁 synchronized优化 内 ...

  2. JavaScript学习系列5 ---ES6中的var, let 和const

    我们都知道JavaScript中的var,在本系列的 JavaScript学习系列2一JavaScript中的变量作用域 中,我们详细阐述了var声明的变量的作用域 文章中提到,JavaScript中 ...

  3. JavaScript学习系列之执行上下文与变量对象篇

    一个热爱技术的菜鸟...用点滴的积累铸就明日的达人 正文 在上一篇文章中讲解了JavaScript内存模型,其中有提到执行上下文与变量对象的概念.对于JavaScript开发者来说,理解执行上下文与变 ...

  4. 【JVM】JVM系列之内存模型(六)

    一.前言 经过前面的学习,我们终于进入了虚拟机最后一部分的学习,内存模型.理解内存模型对我们理解虚拟机.正确使用多线程编程提供很大帮助.下面开始正式学习. 二.Java并发基础 在并发编程中存在两个关 ...

  5. JVM学习总结一——内存模型

    JVM是java知识体系的基石之一,任何一个java程序的运行,都要借助于他.或许对于我这种初级程序员而言,工作中很少有必要刻意去关注JVM,然而如果能对这块知识有所了解,就能够更清晰的明白程序的运行 ...

  6. 浅谈JavaScript原型图与内存模型

    js原型详解 1.内存模型: 1.原型是js中非常特殊一个对象,当一个函数(Person)创建之后,会随之就产生一个原型对象 2. 当通过这个函数的构造函数创建了一个具体的对象(p1)之后,在这个具体 ...

  7. JVM学习记录-Java内存模型(二)

    对于volatile型变量的特殊规则 关键字volatile可以说是Java虚拟机提供的最轻量级的同步机制. 在处理多线程数据竞争问题时,不仅仅是可以使用synchronized关键字来实现,使用vo ...

  8. JVM学习记录-Java内存模型(一)

    前言 Java虚拟机规范中定义了一种Java的内存模型,即Java Memoory Model(简称JMM),用来实现让Java程序在各个平台下都能达到一致的内存访问效果.JVM是整个虚拟机,JMM模 ...

  9. JVM系列.JVM内存模型

    <Java虚拟机规范>将虚拟机的内存分为以下几个区域: 堆区:堆区是JVM中最大的一块内存区域,按照垃圾分代收集的角度划分,又可以分成年轻代和老年代,而年轻代内存又被分成三部分,Eden空 ...

随机推荐

  1. android6.0权限管理工具EasyPermissionUtil

    前言 android6.0開始,权限的申请发生了改变,申请变的动态化,也就是执行时权限,和iOS相仿,动态化的意思是指,在每次使用须要危急权限的方法的时候.须要检查程序是否获得了该权限的许可.动态化的 ...

  2. 本地ubuntu下pycharm 如何利用远程开发环境时显示图片

    最近使用pycharm远程开发tensorflow,每次在想显示图像时,苦于不知怎么操作,就通过保存后再看结果,使得调试很不方便.今天打算解决这个问题,收获也是很多啊. 我首先参考了这两篇博客: ht ...

  3. AutoFac文档8(转载)

    目录 开始 Registering components 控制范围和生命周期 用模块结构化Autofac xml配置 与.net集成 深入理解Autofac 指导 关于 词汇表 泛型 给定一个开放的泛 ...

  4. 动态时间规整-DTW算法

    作者:桂. 时间:2017-05-31  16:17:29 链接:http://www.cnblogs.com/xingshansi/p/6924911.html 前言 动态时间规整(Dynamic ...

  5. RBAC权限模型及数据权限扩展的实践

    话说大家对RBAC权限模型应该是耳熟能详了.但真正用的好的并不多.并且原始的RBAC模型并不包括数据权限的管理,网上也差点儿没有相关的文章可以參考.本人经过几个项目的实战,在其基础上扩展出一套可行的. ...

  6. Atitit.部分错误 设计模式,异常处理框架atiPartErr 的总结

    Atitit.部分错误 设计模式,异常处理框架atiPartErr 的总结 1. 流程图 1 2. Java 类关系结构图片 1 3. 错误信息结构 1 4. 调用 2 4.1. 收集错误信息 3 4 ...

  7. 计算机图形学(一) 视频显示设备_1_CRT原理

    第 1 章 图形系统概述        如今.计算机图形学的作用与应用已经得到了广泛承认.大量的图形硬件和软件系统已经应用 到了差点儿全部的领域.通用计算机甚至很多手持计算器也已经普遍具备 二维及三维 ...

  8. android.animation(2) - ValueAnimator的 Interpolator 和 Evaluator

    一.插值器 插值器,也叫加速器:有关插值器的知识,我在<Animation动画详解(二)——Interpolator插值器>中专门讲过,大家可以先看看这篇文章中各个加速器的效果.这里再讲一 ...

  9. 用log4j将日志写入数据库

    以下为log4j中的配置参数: %m 输出代码中指定的消息 %p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL %r 输出自应用启动到输出该log信息耗费的毫秒数 %t 输出产 ...

  10. systemd启动多实例

    最近用了centos7,启动管理器用的是systemd,感觉很好玩. 1.开机自动启动 新建一个service文件放到/usr/lib/systemd/system/ 比如: [Unit] Descr ...