深拷贝和浅拷贝

一,js中有堆和栈的概念

栈:基本数据类型的值存放在此处

堆:引用数据类型的地址在栈中,真实数据存放在堆中

二,赋值和浅拷贝的区别


var obj1 = {

    name:'ming',

    age:20,

    money:[1,[2,3],[4,5]]

}

// 赋值

var obj2 = obj1;

function shallowCopy(target){

var src = {};

for(var prop in target){

    if(target.hasOwnProperty(prop)){

    src[prop] = target[prop]

    }

}

return src;

}

// 浅拷贝


var obj3 = shallowCopy(obj1);

obj2.name = 'wei';

obj3.age = 30;

obj2.money[0] = '一';

obj3.money[1] = ['二','三'];

console.log(obj1);  //  wei  20  ['一', ['二','三'],[4,5]]

console.log(obj2);  //  wei  20  ['一', ['二','三'],[4,5]]

console.log(obj3);  //  'ming' 30 ['一', ['二','三'],[4,5]]

赋值:同一个引用对象,原对象任何改变都是引起新赋值的改变

浅拷贝:不同的引用对象,若只有一层,则算是深拷贝;引用对象的属性如果是引用数据类型,则会引起新对象的改变

三,浅拷贝和深拷贝

浅拷贝的复制指向原对象的指针(这里指的是一层之后的引用赋值,对于第一层的简单数据类型,则是传值赋值),深拷贝创建一个一模一样的对象,不共享内存,新旧之间没有任何关联

四,浅拷贝的三种实现方式

1,Object.assign()(Object对象的拷贝)


var obj1 = {

    name:'ming',

    age:20,

    money:[1,[2,3],[4,5]]

}

var obj2 = Object.assign({},obj1);

obj2.money[0] = '一'

console.log(obj1)

和下面一样的是,这里如果只有一层,就是深拷贝

2,Array.prototype.slice()(Array的拷贝)


var arr1 = [1,2,{name:'ming'}]

var arr2 = arr1.concat();

arr2[2].name = 'wei'

console.log(arr1)

3,Array.prorotype.concat()(Array的拷贝)


var arr1 = [1,2,{name:'ming'}];

var arr2 = arr1.slice();

arr2[2].name = 'wei';

console.log(arr1)

五,深拷贝实现

1,JSON.parse(JSON.stringify())

先序列化对象,再解析出来

缺点:无法处理函数


var obj1 = {

    name:'ming',

    age:20,

    money:[1,[2,3],[4,5]],

    function(){}

}

// obj拷贝,函数不存在

var arr1 = [1,2,{name:'ming'},function(){}]

// 数组拷贝,函数为null

var obj2 = JSON.parse(JSON.stringify(arr1));

obj2.money[0] = '一';

console.log(obj2)

2,手写递归算法


function checkType(target){

    return Object.prototype.toString.call(target).slice(8,-1);

}

function clone(target){

let result , targetType = checkType(target);

// 判断数据类型

if(targetType === 'Object'){

    result = {};

}else if(targetType === 'Array'){

    result = [];

}else{

    return result;

}

// 开始拷贝

for(let value in target){

    if(checkType(value) === 'Object' || checkType(value) === 'Object'){

    result[value] = clone(value);

}else{

    result[value] = target[value]

    }

}

return result;

}

var obj1 = {

    name:'ming',

    age:20,

    money:[1,[2,3],[4,5]],

    function(){}

}

var obj2 = clone(obj1);

obj2.money = 1

console.log(obj1)

3,lodash库


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

参考地址:

https://juejin.im/post/5b5dcf8351882519790c9a2e#heading-2

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容