栈堆和拷贝

Posted GR07

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了栈堆和拷贝相关的知识,希望对你有一定的参考价值。

1、栈和堆的定义

  栈为自动分配的内存空间,它由系统自动释放;而堆则是动态分配的内存,大小不定也不会自动释放。   

2、栈和堆存放基本类型和引用类型的方式

  基本类型:存放在栈内存中的简单数据段,数据大小确定,内存空间大小可以分配。

  引用类型:对象的地址指针存放在栈内存中,这个指针指向的堆内存中保存着实际数据。

  当我们需要访问引用类型(如对象,数组,函数等)的值时,首先从栈中获得该对象的地址指针,然后再从堆内存中取得所需的数据。

3、传值与传址

  基本类型与引用类型最大的区别实际就是传值与传址的区别。测试用例:

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的时候传的是栈中的地址(相当于新建了一个不同名“指针”),而不是堆内存中的对象。而c仅仅是从a堆内存中获取的一个数据值,并保存在栈中。所以b修改的时候,会根据地址回到a堆中修改,c则直接在栈中修改,并且不能指向a堆内存中。

4、拷贝

 

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);     //1111111 
alert(b.key3);    //33333 
alert(a.key3);    //undefined 

 

a对象中key1属性是字符串,key2属性是数组。a拷贝到b,12属性均顺利拷贝。给b对象新增一个字符串类型的属性key3时,b能正常修改,而a中无定义。说明子对象的key3(基本类型)并没有关联到父对象中,所以undefined。 b.key2.push("大辉"); alert(b.key2);    //小辉,小辉,大辉 alert(a.key2);    //小辉,小辉,大辉   但是,若修改的属性变为对象或数组时,那么父子对象之间就会发生关联。从以上弹出结果可知,我对b对象进行修改,a、b的key2属性值(数组)均发生了改变。其在内存的状态,可以用下图来表示。

其实就是在拷贝后修改引用类型可以关联,新增任何类型都不关联。

以上是关于栈堆和拷贝的主要内容,如果未能解决你的问题,请参考以下文章

深拷贝和浅拷贝

JAVA-初步认识-常用对象API(集合框架-LinkedList集合-练习栈堆和队列)

c语言堆和栈,静态区的理解

JVM -- JVM内存结构:程序计数器虚拟机栈本地方法栈堆方法区

JVM -- JVM内存结构:程序计数器虚拟机栈本地方法栈堆方法区

前端进击的巨人:栈堆队列内存空间