视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
什么是Js中的浅、深拷贝
2020-11-27 20:13:28 责编:小采
文档


现在我们带着问题来学习!

一:什么是堆栈?

??我们都知道:在计算机领域中,堆栈是两种数据结构,它们只能在一端(称为栈顶(top))对数据项进行插入和删除。

  • 栈:队列优先,先进先出;由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。

  • 堆:先进后出;动态分配的空间 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式倒是类似于链表。
    以上都属于计算机基础部分,在此都不详细赘述了,下面我们联系JavaScript来剖析一下堆栈。

  • 二:JavaScript中的基本类型和引用类型与堆栈有什么联系?

    JavaScript的数据类型分为两大种:
    1. 基本类型:Undefined、Null、Boolean、Number 和 String,这5中基本数据类型可以直接访问,他们是按照值进行分配的,存放在栈(stack)内存中的简单数据段,数据大小确定,内存空间大小可以分配。
    2. 引用类型:即存放在堆(heap)内存中的对象,变量实际保存的是一个指针,这个指针指向另一个位置。
    ??以上我们知道了什么是堆栈,和JavaScript的数据类型,下面我们根据js的数据类型来说明一下他们的拷贝情况:

    var obj1 = {name:'bangbang',age:18};
    var b = obj1;
    var c = obj1.age;
    
    console.log(b.name); //bangbang
    console.log(c); //18//改变b和c的值
    b.name = 'yanniu';
    c = 22;
    console.log(obj1.name); //yanniu
    console.log(obj1.age); //18

    ??以上看出:当我们改变b的数据的时候,我们看到了obj1.name的数据也在改变,但是我们改变c的数据的时候发现,obj1.age的值没有变化,这说明了:b和obj1变量操作的是同一个对象,c和obj1完全的。图示如下:

    三:什么是浅拷贝?

    ??根据上面的陈述,基本类型拷贝的时候只是在内存中又开辟了新的空间,和它的父元素(再次我们称被拷贝的对象为父元素)属于 互不想干的东西,因此深浅拷贝是相对于引用类型的,以便于我们对引用类型父对象的保存! 嘿嘿!我们接着看!
    例如:

    var father1 = {name:'shangdi',age:1000,job:['teacher','cook']};//浅拷贝函数
    function copy(obj){ 
    var childs = {}; 
    for(var key in obj){
     childs[key] = obj[key];
     } return childs;
    }var child1 = copy(father1);
    console.log(child1); //{ name: 'shangdi', age: 1000 }
    console.log(typeof child1); //object
    
    //改变子对象的name属性,发现对父对象的name没有影响 哈哈!
    child1.name = 'bangbang';
    console.log(father1); //{ name: 'shangdi', age: 1000 }
    console.log(child1); //{ name: 'bangbang', age: 1000 }
    //注意:这次改变子对象的job属性也就是改变数组,//发现对父对象的job竟然有影响,吓死宝宝了,那怎么办呢,那这个copy有什么用呢是吧!
    child1.job.push('programer');
    console.log(father1); //{ name: 'shangdi',age: 1000,job: [ 'teacher', 'cook', 'programer' ] }
    console.log(child1); //{ name: 'shangdi',age: 1000,job: [ 'teacher', 'cook', 'programer' ] }

    由上面可分析:浅拷贝的时候,当我们改变子对象的数组的时候,父对象竟然也跟着改变,也就是说:子对象和父对象在浅拷贝的时候他们指向同一个内存的数组:由图所示:

    如果我们想让子对象的拷贝和父对象没有一点关联,那么我们就必须用到深度拷贝!嘿嘿!儿子也不能完全跟着爹长啊!

    四:什么是深度拷贝?

    深度拷贝就是把父对象拷贝到子对象上,而且两者的内存和以后的操作都互不影响的拷贝!

     function deepCopy(obj){
     var o; 
     switch(typeof obj){ 
     case 'undefined': break; 
     case 'string' : o = obj + '';break; 
     case 'number' : o = obj - 0;break; 
     case 'boolean' : o = obj;break; 
     case 'object' : 
     if(obj === null){
     o = null;
     }else{ 
     if(obj instanceof Array){
     o = []; 
     for(var i = 0, len = obj.length; i < len; i++){
     o.push(deepCopy(obj[i]));
     }
     }else{
     o = {}; 
     for(var k in obj){
     o[k] = deepCopy(obj[k]);
     }
     }
     } 
     break; 
     default:
     o = obj;break;
     } 
     return o;
     }


    ?? 下面是一些克隆的方法供大家参考,不过他们有区别,自己试验:
    方法二:最简单的

     function deepCopy(obj) {
     return JSON.parse(JSON.stringify(obj));
     }

    方法三:

     function deepCopy(obj){
     var newobj, obj; 
     if (obj.constructor == Object){
     newobj = new obj.constructor();
     }else{
     newobj = new obj.constructor(obj.valueOf());//valueOf()方法返回 Array 对象的原始值
     } 
     for(var key in obj){ 
     if ( newobj[key] != obj[key] ){ 
     if ( typeof(obj[key]) == 'object' ){
     newobj[key] = deepCopy(obj[key]);
     }else{
     newobj[key] = obj[key];
     }
     }
     }
     newobj.toString = obj.toString;
     newobj.valueOf = obj.valueOf; 
     return newobj;
     }

    方法四:

    var cloneObj = function(obj){
     var str, newobj = obj.constructor === Array ? [] : {}; 
     if(typeof obj !== 'object'){ 
     return;
     } else if(window.JSON){
     str = JSON.stringify(obj), //系列化对象
     newobj = JSON.parse(str); //还原
     } else { 
     for(var i in obj){
     newobj[i] = typeof obj[i] === 'object' ? 
     cloneObj(obj[i]) : obj[i]; 
     }
     } return newobj;
    };

    方法五:(JavaScript面向对象编程指南)

     function deepCopy(p,c){
     c = c || {}; 
     for (var i in p){ 
     if(p.hasOwnProperty(i)){ 
     if(typeof p[i] === 'object'){
     c[i] = Array.isArray(p[i]) ? [] : {};
     deepCopy(p[i],c[i]);
     }else{
     c[i] = p[i];
     }
     }
     } return c;
     }

    下载本文
    显示全文
    专题