首页 > 代码库 > javascript --- 深拷贝

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;}

我们创建一个对象,该对象包括数组和子对象:

var parent = {    number: [1,2,3],    letter: [‘a‘, ‘b‘, ‘c‘];    obj: {        prop: 1    },    bool: true}

下面是之前的浅拷贝:

function extendCopy(parent){    var child = {};    for(var i in parent){        child[i] = parent[i];    }    child.usber = parent;    return child;}

 

我们用浅拷贝和深拷贝分别试一下:

var mydeep = deepCopy(parent);var myshallow = extendCopy(parent);mydeep.number.push(4,5,6);mydeep.number; // [1,2,3,4,5,6]parent.number; // [1,2,3]myshallow .number.push(10);myshallow .number; // [1,2,3,10]parent.number; // [1,2,3,10]

 

在使用深拷贝的时候要注意两点:

  1. 在拷贝每个属性之前,建议使用hasOwnPrototype()来确认不会误拷贝不需要的继承属性。

  2. 由于区分Array对象和普通对象Object相当繁琐,所以ES5实现了Array.isArray()函数。

if(Array.isArray !== ‘function‘){    Array.isArray = function(candidate){        return Object.prototype.toString.call(candidate) === ‘[Object Array]‘;    }}

 

 

Object()

我们可以用object()来接收父对象,并返回一个以该对象为原型的新对象。

function object(o){    function F(){};    F.prototype = o;    return new F();}

 

如果我们要访问uber属性,可以继续:

function object(o){    var n;    function F(){};    F.prototype = o;    n = new F();    n.uber  = o;    return n;}

 

这个函数的使用与浅拷贝基本相同:

var a = object(o);o.name = ‘Anna‘;

 

这种模式也被称作原型继承,因为我们在这里将父对象设置成为了子对象的原型。javascript里更名为Object.create()。

var b = Object.create(a);

 

javascript --- 深拷贝