Js的深浅拷贝

转载于:https://www.cnblogs.com/136asdxxl/p/8645750.html

一、js 数据类型

javaScritp的数据类型有:数值类型、字符串类型、布尔类型、null、undefined、对象(数组、正则表达式、日期、函数),大致分成两种:基本数据类型和引用数据类型,
其中:
(1)基本数据类型:数值、字符串、布尔、null、undefined (值类型
(2)复杂(复合)数据类型:对象 (引用类型)

基本数据类型保存在栈内存,引用类型保存在堆内存中。根本原因在于保存在栈内存的必须是大小固定的数据,引用类型的大小不固定,只能保存在堆内存中,但是可以把它的地址写在栈内存中以供我们访问。

如果是基本数据类型,则按值访问,操作的就是变量保存的值;如果是引用类型的值,我们只是通过保存在变量中的引用类型的地址来操作实际对象。

var a = 1;//定义了一个number类型
var obj1 = {//定义了一个object类型
    name:'obj'
};
基本数据类型

1、基本类型的复制

var a = 1;
var b = a;//复制
console.log(b)//1
a = 2;//改变a的值
console.log(b)//1

赋值的时候,在栈内存中重新开辟内存,存放变量b,所以在栈内存中分别存放着变量a、b各自的值,修改时互不影响。


2、引用类型的复制

var color1 = ['red','green'];
var color2 = color1;//复制
console.log(color2)//['red','green'];
color1.push('black') ;//改变color1的值
console.log(color2)//['red','green','black']

color1与color2指向堆内存中同一地址的同一对象,复制的只是引用地址。


引用类型

二、深浅拷贝 :

浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。

1、浅拷贝
浅拷贝只是拷贝基本类型的数据,如果父对象的属性等于数组或另一个对象,那么实际上,子对象获得的只是一个内存地址,因此存在父对象被篡改的可能,浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。

var Nation = {  
            nation: '中国'
        };function extendCopy(p) {  
            var c = {};  
            for (var i in p) {    
                c[i] = p[i];  
            }  
            return c;
        }
        var Doctor = extendCopy(Nation);
        Doctor.career = '医生';
        Doctor.nation = '美国';
        console.log(Doctor.nation); // 美国
        console.log(Nation.nation); // 中国
        console.log(Doctor.career); // 医生
        console.log(Doctor.__proto_ === Nation.__proto_) // true
     // 这里涉及到使用拷贝父对象的属性实现继承
var obj = {
          a: "hello",
          b:{
              a: "world",
              b: 21
            },
          c:["Bob", "Tom", "Jenny"],
          d:function() {
              alert("hello world");
            }
        }
       
        var obj1 = simpleClone(obj);
        console.log('obj1=>>>',obj1);
        // 1、
        obj1.c = ['mm', "Tom", "Jenny"]; // 一层,作为整体,重写,全改变;改变属性值,不改变原对象
        console.log('obj=>>>',obj); //obj.c => ["Bob", "Tom", "Jenny"]
     // 2、
       obj1.c[0] = 'mm'; // 浅拷贝时,改变属性的属性值,改变原对象
        console.log('obj=>>>',obj); //obj.c => ["mm", "Tom", "Jenny"]



浅拷贝函数:

function simpleClone(initalObj) {    
          var obj = {};    
          for ( var i in initalObj) {
            obj[i] = initalObj[i];
          }    
          return obj;
        }



2、深拷贝

深拷贝就是能够实现真正意义上的数组和对象的拷贝。递归调用"浅拷贝"。(深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象)

深拷贝函数:

写法一:
        function deepClone(initalObj, finalObj) {
            var obj = finalObj || {};
            for (var i in initalObj) {
                var prop = initalObj[i];
          
                // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况
                if(prop === obj) {
                    continue;
                }
          
                if (typeof prop === 'object') {
                    obj[i] = (prop.constructor === Array) ? [] : {};
                    arguments.callee(prop, obj[i]);
                } else {
                    obj[i] = prop;
                }
            }
            return obj;
        }

写法二:
        function deepClone(initalObj, finalObj) {
            var obj = finalObj || {};
            for (var i in initalObj) {
                var prop = initalObj[i];
          
                // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况
                if(prop === obj) {
                    continue;
                }
          
                if (typeof prop === 'object') {
                    obj[i] = (prop.constructor === Array) ? [] : Object.create(prop);
                } else {
                    obj[i] = prop;
                }
            }
            return obj;
        }
写法三:

        也可以通过利用 JSON 对象中的 parse 和 stringify 方法,将一个对象转换为字符串,赋给新的对象,再转回JSON对象。


三、深拷贝的应用实例

// jquery 有提供一个$.extend可以用来做 Deep Copy。
        var $ = require('jquery');
        var obj1 = {
            a: 1,
            b: { f: { g: 1 } },
            c: [1, 2, 3]
        };
        var obj2 = $.extend(true, {}, obj1);
        console.log(obj1.b.f === obj2.b.f);
        // false
        
        // 函数库lodash,有提供_.cloneDeep用来做 Deep Copy。
        var _ = require('lodash');
        var obj1 = {
            a: 1,
            b: { f: { g: 1 } },
            c: [1, 2, 3]
        };
        var obj2 = _.cloneDeep(obj1);
        console.log(obj1.b.f === obj2.b.f);
        // false



加油哦!

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

推荐阅读更多精彩内容

  • JS关于基础类型和引用类型的数据请点击:JS数据类型请充分理解之后再来看这篇文章哦~ 基本类型的拷贝 先来看一段非...
    李博洋li阅读 875评论 0 1
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,092评论 1 32
  • js的深浅拷贝可以分为数组的深浅拷贝和对象的深浅拷贝 一、数组的深浅拷贝如果只是简单的将数组中的元素付给另外一个数...
    码老二阅读 538评论 0 1
  • 1.设计模式是什么? 你知道哪些设计模式,并简要叙述?设计模式是一种编码经验,就是用比较成熟的逻辑去处理某一种类型...
    龍飝阅读 2,140评论 0 12
  • 内存管理 简述OC中内存管理机制。与retain配对使用的方法是dealloc还是release,为什么?需要与a...
    丶逐渐阅读 1,950评论 1 16