关于JS浅拷贝与深拷贝

在 JS 中有一些基本类型像是NumberStringBoolean,而对象就是像这样的东西{ name: 'Larry', skill: 'Node.js' },对象跟基本类型最大的不同就在于他们的传值方式。

 

var a = 25;

var b = a;

b = 18;

console.log(a);//25

console.log(b);//18

基本类型是按值传递,像是这样:在修改a时并不会改到b

但对象就不同,对象传的是按引用传值:

 

var obj1 = { a: 10, b: 20, c: 30 };

var obj2 = obj1;

obj2.b = 100;

console.log(obj1);

// { a: 10, b: 100, c: 30 } <-- b 被改到了

console.log(obj2);

// { a: 10, b: 100, c: 30 }

复制一份obj1叫做obj2,然后把obj2.b改成100,但却不小心改到obj1.b,因为他们根本是同一个对象,这就是所谓的浅拷贝。

要避免这样的错误发生就要写成这样:

 

var obj1 = { a: 10, b: 20, c: 30 };

var obj2 = { a: obj1.a, b: obj1.b, c: obj1.c };

obj2.b = 100;

console.log(obj1);

// { a: 10, b: 20, c: 30 } <-- b 沒被改到

console.log(obj2);

// { a: 10, b: 100, c: 30 }

这样就是深拷贝,不会改到原本的obj1。

 

 

浅拷贝(Shallow Copy) VS 深拷贝(Deep Copy)

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

 

 

深拷贝的实现方式

要完全复制又不能修改到原对象,这时候就要用 Deep Copy,这里会介绍几种Deep Copy 的方式。

1、手动复制

把一个对象的属性复制给另一个对象的属性

 

var obj1 = { a: 10, b: 20, c: 30 };

var obj2 = { a: obj1.a, b: obj1.b, c: obj1.c };

obj2.b = 100;

console.log(obj1);

// { a: 10, b: 20, c: 30 } <-- 沒被改到

console.log(obj2);

// { a: 10, b: 100, c: 30 }

但这样很麻烦,要一个一个自己复制;而且这样的本质也不能算是 Deep Copy,因为对象里面也可能会是对象,如像下面这个状况:

 

var obj1 = { body: { a: 10 } };

var obj2 = { body: obj1.body };

obj2.body.a = 20;

console.log(obj1);

// { body: { a: 20 } } <-- 被改到了

console.log(obj2);

// { body: { a: 20 } }

console.log(obj1 === obj2);

// false

console.log(obj1.body === obj2.body);

// true

虽然obj1obj2是不同对象,但他们会共享同一个obj1.body所以修改obj2.body.a时也会修改到旧的。

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;

}

var str = {};

var obj = { a: {a: "hello", b: 21} };

deepClone(obj, str);

console.log(str.a);

3、jquery/zepot

jquery/zepot有提供一个$.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);

4、lodash

另外一个很热门的函数库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

这个性能还不错,使用起来也很简单。

转载于:https://blog.csdn.net/QQ408896436/article/details/79343481

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值