JS堆和栈的概念回忆

又有一段时间没有总结自己的所学所用了,懒惰无时无刻不在,还是要强迫自己做点什么来提醒自己掌握了哪些。今天回忆了一下当初刚接触javascript时,所学到的关于堆和栈的概念,那时候是一头雾水,从文字表面根本发现不了其含义,更不知道堆栈的区别是什么,但是这个知识点其实在我们编写js代码时,处处都在用到。今晚趁着睡意未到,来总结回忆一波,各位兄台可以多多指教,小弟感激不尽。

一: 数据类型

为了更好容易的理解堆和栈,首先来复习一下js中的数据类型。
在js中数据类型主要分为以下两大类:

  • 基本类型:String,Number,Boolean,Null,Undefined,这5种基本数据类型它们是直接按值存放的,所以可以直接访问。
  • 引用类型:Function,Array,Object,当我们需要访问这三种引用类型的值时,首先得从栈中获得该对象的地址指针,然后再从堆内存中取得所需的数据。

现在咱再来瞅一瞅概念,什么是堆,什么是栈!

二: 什么是堆什么是栈

其实了解过一些数据结构的兄台应该都对堆和栈有一定的认识,堆栈不仅仅只有js中才有这个概念,不过这片文章只针对js来进行描述。

  • 栈(stack): 由操作系统自动分配内存空间,自动释放,存储的是基础变量以及一些对象的引用变量,占据固定大小的空间。
  • 堆(heap):由操作系统动态分配的内存,大小不定也不会自动释放,一般由程序员分配释放,也可由垃圾回收机制回收。

三: 堆和栈的区别

1、栈:基础变量的值是存储在栈中,而引用变量存储在栈中的是指向堆中的数组或者对象的地址,这就是为何修改引用类型总会影响到其他指向这个地址的引用变量。
优点:相比于堆来说存取速度会快,并且栈内存中的数据是可以共享的,例如同时声明了var a = 1和var b = 1,会先处理a,然后在栈中查找有没有值为1的地址,如果没有就开辟一个值为1的地址,然后a指向这个地址,当处理b时,因为值为1的地址已经开辟好了,所以b也会同样指向同一个地址。
缺点:相比于堆来说的缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。

2、堆:堆内存中的对象不会随方法的结束而销毁,就算方法结束了,这个对象也可能会被其他引用变量所引用(参数传递)。创建对象是为了反复利用(因为对象的创建成本通常较大),这个对象将被保存到运行时数据区(也就是堆内存)。只有当一个对象没有任何引用变量引用它时,系统的垃圾回收机制才会在核实的时候回收它。
关于堆的优缺点大家只要看一下栈的优缺点相信就会有自己的判断了。

四: 传值与传址

基本类型与引用类型最大的区别实际就是传值与传址的区别。瞅一瞅这个例子:

var a = [1,2,3,4,5];
var b = a;
var c = a[0];
alert(b);//[1,2,3,4,5] 
alert(c);//1 
//改变数值         
b[4] = 6;
c = 7;
alert(a[4]);//6
alert(a[0]);//1

以上的例子中可以看出改变b的值时,a的数组也发生了改变;但是改变c的值时,a的数组毫无变化,这个就是传值和传址的区别。
因为a是数组,属于引用类型,所以它赋予给b的时候传的是栈中的地址(指向a这个数组在堆内存中的地址),而不是直接传的堆内存中的对象,当b发生改变时,也就会根据地址回到a在堆内存中的位置进行修改;而c仅仅是从a在堆内存中获取的一个数据值,并保存在栈中,所以c是直接在栈中修改,并且不能指向a在堆内存中的地址。


传值和传址简图

五: 深浅拷贝

1、浅拷贝:直接来例子,看完例子在讲解。

var a = {
         key1:"11111"
    }
function Copy(p) {
var c = {};
for (var i in p) { 
           c[i] = p[i];
        }
return c;
  }
     a.key2 = ['小辉','小辉'];
var b = Copy(a);
    b.key3 = '33333';
     alert(b.key1);     //11111
     alert(b.key3);    //33333
     alert(a.key3);    //undefined

b.key2.push("大辉");
alert(b.key2);    //小辉,小辉,大辉
alert(a.key2);    //小辉,小辉,大辉

从以上例子可以看出浅拷贝其实可以理解成只拷贝属性的第一层,在复制属性的基本类型时,直接用等号完成,如果遇到属性还是引用类型就会先将堆内存中的地址复制过去。
a对象中key1属性是字符串,key2属性是数组。a拷贝到b,key1和key2属性均顺利拷贝。给b对象新增一个字符串类型的属性key3时,b能正常修改,而a中无定义。说明子对象的key3(基本类型)并没有关联到父对象中,所以undefined。
但是,若修改的属性变为对象或数组时,那么父子对象之间就会发生关联,因为指向的堆内存中的地址是同一个。从以上弹出结果可知,我对b对象进行修改,a、b的key2属性值(数组)均发生了改变。其在内存的状态,可以用下图来表示。


浅拷贝

2、深拷贝:如果我们希望父子对象在任何时候都不产生关联,那我们就得用深度拷贝了,其实就是用递归的方法将引用类型的属性都赋值给子对象就可以了。瞅例子:

function Copy(p, c) {
var c = c || {};
for (var i in p) {
if (typeof p[i] === 'object') {
              c[i] = (p[i].constructor === Array) ? [] : {};
             Copy(p[i], c[i]);
           } else {
              c[i] = p[i];
          }
        }
return c;
  }    
     a.key2 = ['小辉','小辉'];
var b={};
     b = Copy(a,b);        
     b.key2.push("大辉");
     alert(b.key2);    //小辉,小辉,大辉
     alert(a.key2);    //小辉,小辉

由上可知,修改b的key2数组时,没有使a父对象中的key2数组新增一个值,即子对象没有影响到父对象a中的key2。简单的理解就是此时此刻,b中key2的数组和a中key2的数组虽然赋值相同,但是指向堆内存中的地址已经不是同一个了,所以不管修改哪一个key2都不会影响到另一个。其存储模式大致如下:


深拷贝

六: 堆和栈的溢出

如果想要堆溢出,比较简单,可以循环创建对象或大的对象;
如果想要栈溢出,可以递归调用方法,这样随着栈深度的增加,JVM (虚拟机)维持着一条长长的方法调用轨迹,直到内存不够分配,产生栈溢出。

关于堆和栈的概念就讲到这里咯,有任何问题或者不同见解的,再或者遗漏哪些重要知识点的,都欢迎各位大牛们留言解答,小弟感激不尽~~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,383评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,522评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,852评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,621评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,741评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,929评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,076评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,803评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,265评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,582评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,716评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,395评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,039评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,027评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,488评论 2 361
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,612评论 2 350

推荐阅读更多精彩内容