美文网首页
1.2堆栈与拷贝

1.2堆栈与拷贝

作者: 请叫我小飞鹅 | 来源:发表于2017-03-10 18:35 被阅读0次

1.传值与传址

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

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堆内存中。

2.浅拷贝

前面已经提到,在定义一个对象或数组时,变量存放的往往只是一个地址。当我们使用对象拷贝时,如果属性是对象或数组时,这时候我们传递的也只是一个地址。因此子对象在访问该属性时,会根据地址回溯到父对象指向的堆内存中,即父子对象发生了关联,两者的属性值会指向同一内存空间。

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。

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

但是,若修改的属性变为对象或数组时,那么父子对象之间就会发生关联。从以上弹出结果可知,我对b对象进行修改,a、b的key2属性值(数组)均发生了改变。其在内存的状态,可以用下图来表示。



  原因是key1的值属于基本类型,所以拷贝的时候传递的就是该数据段;但是key2的值是堆内存中的对象,所以key2在拷贝的时候传递的是指向key2对象的地址,无论复制多少个key2,其值始终是指向父对象的key2对象的内存空间。

3.深拷贝

或许以上并不是我们在实际编码中想要的结果,我们不希望父子对象之间产生关联,那么这时候可以用到深拷贝。既然属性值类型是数组和或象时只会传址,那么我们就用递归来解决这个问题,把父对象中所有属于对象的属性类型都遍历赋给子对象即可。测试代码如下:

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。其存储模式大致如下:


可能会有点绕,但总结的说就是:
如果是基本类型,直接复制值。
如果是引用类型的:浅拷贝是复制地址。深拷贝,是重新在内存里建了一块,用来存要拷贝对象的值。。

相关文章

  • 1.2堆栈与拷贝

    1.传值与传址 基本类型与引用类型最大的区别实际就是传值与传址的却别。 从上面我们可以得知,当我改变b中的数据时,...

  • JS堆栈与拷贝

    原文:http://www.cnblogs.com/jingwhale/p/4884759.html 一.堆栈的定...

  • c/c++/c++11 浅拷贝和深拷贝

    目录 1 c++拷贝 1.1 拷贝构造函数1.2 浅拷贝1.3 深拷贝 2 c语言拷贝 2.1 浅拷贝2.2 深拷...

  • js堆栈理解、实现浅拷贝与深拷贝

    1.何为堆栈? 堆(heap)用于引用数据类型(数组,对象,函数)分配空间,由程序员分配释放,从栈内存指向堆内存的...

  • js的浅拷贝与深拷贝

    js的浅拷贝与深拷贝 涉及知识点: js中的数据类型(基本类型,引用类型) js中的存储数据的堆栈相关知识点; 下...

  • 堆栈及深拷贝浅拷贝

    什么是堆栈? 堆:队列优先,先进先出;由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于...

  • JavaScript - 堆与栈、浅拷贝与深拷贝

    堆与栈是什么,与浅拷贝和深拷贝有什么联系? 在计算机领域,堆栈是两种数据结构,都是一种数据项按序排列的数据结构,只...

  • web前端常见面试题

    面试常见问题总结 JavaScript 原型 数据存储 : 堆栈 深拷贝 数组去重 null undefined...

  • js类型转换

    目录 :字符类型转换数字类型转换布尔类型转换堆栈垃圾回收深拷贝浅拷贝任意类型转字符串1,String(x) 2,x...

  • 数据结构与算法复习(一)

    1. 数据结构 1.1 堆栈(Stack) 后进先出(LIFO, Last In First Out) 1.2 队...

网友评论

      本文标题:1.2堆栈与拷贝

      本文链接:https://www.haomeiwen.com/subject/yplogttx.html