最简js深浅拷贝说明

时间:2022-07-08 19:49:20

1.浅拷贝

  浅拷贝是拷贝引用,拷贝后的引用都是指向同一个对象的实例,彼此之间的操作会互相影响。

    浅拷贝分两种情况:

        1、直接拷贝源对象的引用

        2、 源对象拷贝实例,但其属性对象(类型为ObjectArray的属性)拷贝引用

  直接拷贝源对象的引用

//最简单的例子
var
a = {c:1};var b = a;
console.log(a
=== b); // 输出true。
a.c = 2;
console.log(b.c);
// 输出 2,,这里就是拷贝了对象的引用,从而两边都改变了

  源对象拷贝实例,其属性对象拷贝引用

  说明:外层源对象是拷贝实例,当其属性元素为复杂数据类型时,内层元素拷贝引用。这时对源对象直接操作,不影响两对象,但是对其属性操作时候,会改变两对象的属性的值。
  常用方法为:Array.prototype.slice()Array.prototype.concat()jQury$.extend({},obj)

var a = [{c:1}, {d:2},2];
var b =
a.slice();
console.log(a
=== b); // 输出false,说明外层数组拷贝的是实例
a[0].c = 3;
console.log(b[
0].c); // 输出 3,说明其元素拷贝的是引用
a[2]=4;
console.log(b[2]); //输出 2,不是复杂数据类型,所以没有变,没有引用

 

2.深拷贝

  将重新分配内存,并且把源对象所有属性都进行新建拷贝,以保证对象的引用图不包含任何原有对象或对象图上的任何对象,拷贝后的对象与原来的对象是完全隔离,互不影响。

 深拷贝

说明:深拷贝后,两个对象,包括其内部的元素互不干扰。常见方法有JSON.parse(),JSON.stringify()jQury$.extend(true,{},obj):

b = JSON.parse( JSON.stringify(a) )//最简单的深拷贝

  但有局限性:

  • 无法复制函数
  • 原型链没了,对象就是object,所属的类没了

jQury$.extend(true,{},obj):

var a = {c: {d: 1}};
var b = $.extend(true, {}, a);
console.log(a
=== b); // 输出false
a.c.d = 3;
console.log(b.c.d);
// 输出 1,没有改变。

深拷贝本质理解:将原对象各个属性所包含的对象也依次采用深复制的方法“递归复制”到新对象上。这就不会存在上面 obj 和 shadowObj 的 arr 属性指向同一个对象的问题。例:

var deepCopy= function(source) { 
var result={};
for (var key in source) {
result[key]
= typeof source[key]===’object’? deepCoyp(source[key]): source[key];
}
return result;
}//通过递归调用复制对对象上的每一个子类进行复制,从而达到时属性指向不同对象

复杂全面的代码,可以学习借鉴

function() {
function _type(value) {
return Object.prototype.toString.call(value).slice(8).slice(0, -1).toLowerCase();
}

function isArray(value) {
return _type(value) == 'array';
}

function isObject(value) {
return _type(value) == 'object';
}

function cloneArray(src, dest) {
src.forEach(function(item, index) {
if (isArray(item)) {



console.log(
'yes')
dest[index]
= [];
copy(src[index], dest[index]);
}
else {
dest[index]
= src[index];
}
});


}

function cloneObject(src, dest) {
for (var key in src) {
// filter 原型链上面的属性
if (src.hasOwnProperty(key)) {
if (isObject(src[key])) {
// 判断循环引用的问题
if (src[key] === src) {
dest[key]
= src;
}
else {
dest[key]
= {};
copy(src[key], dest[key]);
}
}
else if (isArray(src[key])) {

dest[key]
= [];
cloneArray(src[key], dest[key])


}
else {
dest[key]
= src[key];

}
}
}

}


function cloneDeep(src) {
if (isArray(src)) {
var dest = [];
cloneArray(src, dest);
}
if (isObject(src)) {

var dest = {};
cloneObject(src, dest);

}
return dest;
}


window.clone
= cloneDeep;


})();

 

如有错误欢迎留言改正……