js 自动分配金额_JS内存图以及原型与原型链

内存以及内存图

在JS中,每一个数据都需要一个内存空间。内存空间又被分为两种,栈内存(stock)与堆内存(heap)JS内存空间分为栈(stack)、堆(heap)、池(一般也会归类为栈中)。 其中栈存放变量,堆存放复杂对象,池存放常量。

JS中的基础数据类型,这些值都有固定的大小,往往都保存在栈内存中(闭包除外),由系统自动分配存储空间。我们可以直接操作保存在栈内存空间的值,因此基础数据类型都是按值访问 数据在栈内存中的存储与使用方式类似于数据结构中的堆栈数据结构,遵循后进先出的原则。 基础数据类型: Number String Null Undefined Boolean ~ ~ 要简单理解栈内存空间的存储方式,我们可以通过类比乒乓球盒子来分析。

72c2872c23f3a3c9bf413f25180ba65f.png

这种乒乓球的存放方式与栈中存取数据的方式如出一辙。处于盒子中最顶层的乒乓球5,它一定是最后被放进去,但可以最先被使用。而我们想要使用底层的乒乓球1,就必须将上面的4个乒乓球取出来,让乒乓球1处于盒子顶层。这就是栈空间先进后出,后进先出的特点。

JS的复杂数据类型,比如数组Array,它们值的大小是不固定的。引用数据类型的值是保存在堆内存中的对象。JS不允许直接访问堆内存中的位置,因此我们不能直接操作对象的堆内存空间。在操作对象时,实际上是在操作对象的引用而不是实际的对象。因此,引用类型的值都是按引用访问的。这里的引用,我们可以粗浅地理解为保存在栈内存中的一个地址,该地址与堆内存的实际值相关联。 堆存取数据的方式,则与书架与书非常相似。 书虽然也有序的存放在书架上,但是我们只要知道书的名字,我们就可以很方便的取出我们想要的书,而不用像从乒乓球盒子里取乒乓一样,非得将上面的所有乒乓球拿出来才能取到中间的某一个乒乓球。好比在JSON格式的数据中,我们存储的key-value是可以无序的,因为顺序的不同并不影响我们的使用,我们只需要关心书的名字。

JS里所有的数字都是以64位浮点数储存的,16位存储一个字符,所以在栈内存内都是64位01
我们来看看代码:

var a = 20
var b = a
b=30

b=a,那就把a存的东西复制然后覆盖到b储存的地方。

1665f1199ccf3cd53420ae1b3161acae.png

在栈内存中的数据发生复制行为时,系统会自动为新的变量分配一个新值。var b = a执行之后,a与b虽然值都等于20,但是他们其实已经是相互独立互不影响的值了。具体如图。所以我们修改了b的值以后,a的值并不会发生变化。

再复杂一点,我们存储复杂类型呢?也就是heap内存里是怎样呢?

var m = { a: 10, b: 20 }
var n = m;
n.a = 15;// 这时m.a的值是多少

就像上述代码,当需要存储字符的时候,一行64位浮点数,只能存储4个字符,非常浪费且再添加属性的时候就需要整体移动下位的代码,很麻烦,所以我们就在栈内存里存储一个地址,地址随意,但是这个地址指向heap内存里相应地址的位置,而我们需要储存的内容就写在这里。
我们通过var n = m执行一次复制引用类型的操作。引用类型的复制同样也会为新的变量自动分配一个新的值保存在栈内存中,但不同的是,这个新的值,仅仅只是引用类型的一个地址指针。当地址指针相同时,尽管他们相互独立,但是在堆内存中访问到的具体对象实际上是同一个。

如图所示

4cb1f1605bc1a24032d5a376c1c8f385.png

因此当我改变n时,m也发生了变化。这就是引用类型的特性。

以上就是js中的内存和内存图,遇到不明白的地方,多画图就能弄明白了。

内存释放

因为JavaScript具有自动垃圾收集机制,JavaScript的内存生命周期是

1. 分配你所需要的内存
2. 使用分配到的内存(读、写)
3. 不需要时将其释放、归还

为了便于理解,我们使用一个简单的例子来解释这个周期。

var a = 20;  // 在内存中给数值变量分配空间
alert(a + 100);  // 使用内存
a = null; // 使用完毕之后,释放内存空间

第一步和第二步我们都很好理解,JavaScript在定义变量时就完成了内存分配。第三步释放内存空间则是我们需要重点理解的一个点。

JavaScript有自动垃圾收集机制,那么这个自动垃圾收集机制的原理是什么呢?其实很简单,就是找出那些不再继续使用的值,然后释放其占用的内存。垃圾收集器会每隔固定的时间段就执行一次释放操作。

var a = {name:'xx'}
var b = {name:'yy'}
// 代码区                    // stack                  //Heapa                        ADDR 888                   xxb                        ADDR 666                   yy
// 当b =a
//代码区                     // stack                  //Heapa                        ADDR 888                   xxb                        ADDR 888                   (yy未被引用,被释放)

在JavaScript中,最常用的是通过标记清除的算法来找到哪些对象是不再继续使用的,因此a = null其实仅仅只是做了一个释放引用的操作,让 a 原本对应的值失去引用,脱离执行环境,这个值会在下一次垃圾收集器执行操作时被找到并释放。而在适当的时候解除引用,是为页面获得更好性能的一个重要方式。

在局部作用域中,当函数执行完毕,局部变量也就没有存在的必要了,因此垃圾收集器很容易做出判断并回收。但是全局变量什么时候需要自动释放内存空间则很难判断,因此在我们的开发中,需要尽量避免使用全局变量。

深拷贝与浅拷贝


var a = 1 var b = a b = 2 a // 1
像这样,b改变不会影响a,这就是深拷贝
对于所有的基本类型,赋值都是深拷贝,所以我们来研究对象。

var a={name:'}
var b=a
b.name='b'
a.name//'b'

如上述,b.name = 'b' ,改变name的值,引用a,得到的也是改变后的。
像这样,b的改变会导致a的改变,就是浅拷贝。

全局对象 window

ECMAScript 规定全局对象叫做 global,但是浏览器把 window 作为全局对象(浏览器先存在的)

window 就是一个哈希表,有很多属性。

window 的属性就是全局变量。

这些全局变量分为两种:

  1. 一种是 ECMAScript 规定的
  • global.parseInt
  • global.parseFloat
  • global.Number
  • global.String
  • global.Boolean
  • global.Object
  1. 一种是浏览器自己加的属性
  • window.alert
  • window.prompt
  • window.comfirm
  • window.console.log
  • window.console.dir
  • window.document
  • window.document.createElement
  • window.document.getElementById

所有 API 都可以在 MDN 里找到详细的资料。

今天我们学习第一种全局变量。

全局函数

  1. Number
    var n = new Number(1) 创建一个 Number 对象
    1 与 new Number(1) 的区别是什么?
  2. String
    var s = new String('hello') 创建一个 String 对象
    'hello' 与 new String('hello') 的区别是什么?
  3. Boolean
    var b = new Boolean(true) 创建一个 Boolean 对象
    true 与 new Boolean(true) 的区别是什么?
  4. Object
    var o1 = {}
    var o2 = new Object()
    o1 和 o2 没区别


上面的区别在于,只要我们引用上述字符串的属性,JavaScript就会将字符串值通过调用new String(s)的方式转换成对象,之后字符串继承了对象的方法,处理属性的引用。属性引用结束,这个新创建的对象就被销毁。
我们可以这样来想,我们既想用简单类型,又想获得对象的方法,然后Branden Eich就想了个办法,我们可以建立临时对象,获取属性后返回给调用,然后销毁就可以。

var n = ‘a'
n.toString()
// 代码区             // stack               // heapn                     'a'temp                  ADDR 888             888: 'a'toSting()valueOf()


temp就是临时对象,当调用toString返回后,temp马上被销毁了。
其他的数据类型也是一样,
调取属性的背后都是这样一套操作。

原型与原型链

从上面我们可以看到,利用new创建并初始化一个新对象,运算符new后面跟着一个函数调用,叫做构造函数。
var s = new String('hello')
如上述代码,s就是被创建的实例对象,new运算符后跟着的String(注意这里开头必须大写来和string区分)就是构造函数。
我们可以看到从实例对象中调用的属性,但是他们都具有的属性比如toString以及valueOf等,如果每个实例对象都在heap存储处生成这些都有的属性岂不是很费内存?所以我们可以共有属性归拢起来,然后通过 __proto__ 来指向共有属性。公用的属性藏在哪

JavaScript中的对象,都有一个内置属性[[Prototype]],指向这个对象的原型对象。当查找一个属性或方法时,如果在当前对象中找不到定义,会继续在当前对象的原型对象中查找;该原型对象也有一个自己的原型对象(__proto__) ,层层向上直到一个对象的原型对象为null。根据定义,null没有原型,并作为这个原型链中的最后一个环节。

可以看出,这个查找过程是一个链式的查找,每个对象都有一个到它自身原型对象的链接,这些链接组件的整个链条就是原型链。拥有相同原型的多个对象,他们的共同特征正是通过这种查找模式体现出来的。
在上面的查找过程,我们提到了最顶层的原型对象,这个对象就是Object.prototype,这个对象中保存了最常用的方法,如toStringvalueOfhasOwnProperty等,因此我们才能在任何对象中使用这些方法。

如下图:

c57493e53ffbd065871dd8692db5a7bd.png

重要公式

var 对象 = new 函数()
对象.__proto__ === 对象的构造函数.prototype// 推论
var number = new Number()
number.__proto__ = Number.prototype
Number.__proto__ = Function.prototype // 因为 Number 是 Function 的实例var object = new Object()
object.__proto__ = Object.prototype
Object.__proto__ = Function.prototype // 因为 Object 是 Function 的实例var function = new Function()
function.__proto__ = Function.prototype
Function.__proto__ == Function.prototye // 因为 Function 是 Function 的实例!

(以上部分资料来自网络,仅供自己学习参考,侵删)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/488462.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

全球首个AI宇宙模拟器不仅有6亿光年宽度,还“自行”跑出了暗物质

来源:大数据文摘《创世纪》里,神用7天创造了这个世界。而现在,你可能也有机会体验这个过程,创造一个属于自己的宇宙。Space Engine 0.990版本在Steam平台发售不到一天,近300测评全部为最高评价。之后,还得到…

js 延迟几秒执行_深入研究 Node.js 的回调队列

// 每日前端夜话 第365篇// 正文共:3000 字// 预计阅读时间:10 分钟队列是 Node.js 中用于有效处理异步操作的一项重要技术。在本文中,我们将深入研究 Node.js 中的队列:它们是什么,它们如何工作(通过事件循环)以及它们…

java官方 jax rs_jboss7 Java API for RESTful Web Services (JAX-RS) 官方文档

原文:https://docs.jboss.org/author/display/AS7/JavaAPIforRESTfulWebServices(JAX-RS)ContentTutorial OverviewThis chapter describes the Java API for RESTful web services (JAX-RS, defined in JSR331). RESTEasy is an portable implementation of this s…

研究揭示大脑在工作记忆中存储信息的神经机制

来源:中国科学院脑科学与智能技术卓越创新中心(神经科学研究所)3月5日,《神经元》期刊在线发表了题为《无颗粒岛叶皮层瞬时性神经元活动调控学习新任务时的工作记忆存储》的研究论文。该研究由中国科学院脑科学与智能技术卓越创新…

[Jmeter] 基本使用的总结

转载于:https://www.cnblogs.com/mytianying/p/6793461.html

java 仿qq登录界面7.1_安卓开发学习笔记(七):仿写腾讯QQ登录注册界面

这段代码的关键主要是在我们的相对布局以及线性布局上面,我们首先在总体布局里设置为线性布局,然后再在里面设置为相对布局,这是一个十分常见的XML布局模式。废话不多说,直接上代码:一.activity.xml>android:layout…

【前沿科技】云计算军事运用有啥特点

来源: 军语开源情报研究所云计算技术被视为继大型计算机、个人计算机、互联网之后的第四次信息技术产业革命。云计算是一种围绕分布式共享计算资源的创新应用模式,资源提供者可以方便而快速地提供计算资源,而无处不在的资源需求者可以便利地使…

js原型和原型链_JS 构造函数与原型链

JavaScript 对象体系是基于构造函数和原型链的。继承不通过类,而是通过原型对象实现,原型对象的所有属性和方法,都能被实例对象共享。构造函数(constructor)在 JS 中想要生成可重用、可继承的对象就要使用构造函数&…

全球制造业的未来

来源:航空简报2020年3月4日,Brahima Coulibaly和Karim Foda在美国布鲁金斯学会官网刊文,分析了全球制造业的未来,提出了几个鲜明的观点:1.“比较优势”将发生转移,中等收入国家尤其是许多亚洲新兴经济体&am…

mybatis 批量修改_解放双手,不写SQL!一个开源 MyBatis 神器!!

什么是通用 Mapper?它是一个可以方便的使用 Mybatis 进行单表的增删改查优秀开源产品。它使用拦截器来实现具体的执行 Sql,完全使用原生的 Mybatis 进行操作。在 Github 上标星 9.6K!为什么要用 Mapper?它提供了所有单表的基本增删…

论文速读:AI能从人类的愚蠢中学到什么?

来源:混沌巡洋舰本文来自对下面论文的编译和解读:导读:随着机器在某些认知问题上超越人类,人机协作将会带来越来越显著的影响。造成人类偏见的三个主要原因(小而不完整的数据集,从自己的决策结果中学习&…

struts2的核心和工作原理

在学习struts2之前,首先我们要明确使用struts2的目的是什么?它能给我们带来什么样的优点? 设计目标 Struts设计的第一目标就是使MVC模式应用于web程序设计。在这儿MVC模式的优点就不在提了。技术优势 Struts2有双方面的技术优势,一…

mysql允许root远程连接_西部数码使用指南:远程桌面之终端服务器超出了最大允许连接数解决...

版权归西部数码所有,原文链接:https://www.west.cn/faq/list.asp?unid739出现这种情况的原因和解决办法。 原因:用远程桌面链接登录到终端服务器时经常会遇到“终端服务器超出最大允许链接数”诸如此类错误导致无法正常登录终端服务器,引起该…

关于征集2020重大科学问题和工程技术难题的通知

来源:中国指挥与控制学会学会全体会员:为研判未来科技发展趋势、前瞻谋划和布局前沿科技领域与方向,瞄准世界科技前沿,推进世界科技强国建设,根据《中国科协办公厅关于征集2020重大科学问题和工程技术难题的通知》精神…

怎么在别人网站注入js脚本_别人的网站是怎么实现引流的?这些站外SEO技巧是关键...

点击上方蓝字关注我们!因为分享,我们相遇在SEO路上“网站上线一段时间了,为什么没有流量?为什么没有询盘?”对于做网络营销的企业而言,网站流量与询盘是建立网站的根本目的,可是为什么操作了一段…

比尔盖茨NEJM发文:新冠肺炎是百年一遇的流行病!全世界应该如何应对?

来源:生物谷面对任何危机,政府都有两个同等重要的责任:解决眼前的问题,并防止它再次发生。COVID-19大流行就是一个恰当的例子。我们现在需要拯救生命,同时也需要改善我们应对疫情的方式。第一点更为紧迫,但…

java实现上传图片代码_Java图片上传实现代码

本文实例为大家分享了java图片上传代码,供大家参考,具体内容如下import java.io.*;import java.net.*;/**发送端*/class picsend{public static void main(String[] args) throws Exception{if(args.length!1){System.out.println("请选择一张.jpg图…

中国数学相比与西方数学为什么会处于劣势?

来源:数学职业家虽然中国人更习惯【中国数学相比与西方数学为什么会处于劣势?】的视角,但私以为问【西欧数学为何可以独步天下】更合适。因为曾经辉煌过的阿拉伯数学、印度数学都落寞了。也没有其他任何地区的文明能达成西欧的成就。另外&…

java的地位和优势,Java语言之所以能持续占领霸主地位 这些优势功不可没

java作为一个真正面向对象语言,驰骋IT界二十余载,一直独占编程语言排行榜榜首,成为广泛使用的开发编程语言,为什么java就能够持续占领霸主地位呢?有哪些必然的优势呢?这首要的优势就是:既然是真…

WebBrowser,挖坑,跳坑,填坑

最近在 C# Asp.net 平台上的一个项目中用到了 WebBrowser 控件。自然而然就进入了 一连串的坑了。用网络上一同行的话“用WebBrowse,就是在给自己挖坑”。 道术太浅,这个坑我还是跳了。 需求:截取网页中的一部分,生成图片。 咣当咣…