Fork me on GitHub

Javascript 对象复制(深浅拷贝)

  • 要弄懂深浅拷贝的概念,着实不易。这里举个不恰当例子便于理解:
    • 浅拷贝是双胞胎
    • 深拷贝是单独克隆自己

数据类型分类:

数据类型分类

指针指向

  • 栈内存、堆内存、指针指向(如下红圈圈的斜线)。
    数据类型存放位置

赋值、拷贝、引用区别

  • 赋值指给一个变量赋予某个值,包含两种方式,一种是直接量,另一种,是将另一个变量的值传递给这个变量。拷贝和引用都属于后者。
  • 引用的目的是将指针指向相同堆内存中的某一位置
  • 拷贝的目的是改变指针的指向,并且内部属性或者元素的值相等

    • 基础数据类型在赋值过程就改变了指针指向,所以通常说,基础类型的引用只存在只读状态
    • 复杂数据类型的指针指向包含两种:一种是指针指向栈内存,另一种是指针指向堆内存,前者只需赋值即可,可后者没那么容易。
    1
    2
    3
    4
    var person =  {
    name: 'lc',
    friends: ['xm','xm','xl']
    }
  • 从这段代码,我们很清楚知道person.nameperson.friends中的每个元素的指针指向栈内存,personperson.friends的指针指向堆内存,由此我们可以得出两点:

    • 拷贝改变复杂数据类型的指针指向,必须是先改变指向堆内存的指针指向,如person的指针指向。
    • 拷贝改变指针指向,可以只改person的指针指向,这类叫做浅拷贝(浅复制);也可以改变personperson.friends等全部指针指向,这类通常叫做深拷贝(深复制)。

浅拷贝和深拷贝

  • 在上面,我已描叙了浅拷贝和深拷贝,在这里再严谨的总结一下:
    • 浅拷贝只改变复杂数据类型内部分的指针指向,也就是不完全改变
    • 深拷贝彻头彻底地改变所有指针指向,也就是完全改变
浅拷贝
  • 以上例代码为例:
    1
    2
    3
    4
    var shallow_copy = {};
    for(var i in person) {
    shollow_copy[i] = person[i];
    }

或者 es6 的 Object.assign()

深拷贝
  • 实现的方法也是多种,大致上可以分为两类: 一类是json,另一类是递归循环遍历赋值。
  • 其中最常见的是JQuery中$.extend()
------ 本文结束 ------