# 我理解的浅拷贝和深拷贝

浅拷贝的方法：

1.直接赋值：

 var obj1 = {a: 1, b: 2};

var obj2 = obj1;

obj2.b = 22;

console.log(obj1.b); // 22

2.Object.assign

var obj1 = {a: 1, b: 2};
var obj2 = {c: 3};
Object.assign(obj1, obj2);
console.log(obj1) // {a: 1, b: 2, c: 3}
obj2.c = 4;
console.log(obj1.c) // 3

var obj1 = {a: 1, b: 2};
var obj2 = {c: {z: 3}};
Object.assign(obj1, obj2);
console.log(obj1); // {a: 1, b: 2, c: {z: 3}}
console.log(obj2); // {c: {z: 3}}
obj2.c.z = 4;
console.log(obj1.c.z); // 4;

3.通过对象扩展运算符 （{ ...obj }）

var obj1 = {
a: 1,
b: 2,
c: {
z: 3
}
};
var obj2 = {...obj1};
console.log(obj2); // { a: 1, b: 2, c: { z: 3 } }

obj1.a = 11;
console.log(obj2.a);  // 1

obj1.c.z = 33;
console.log(obj2.c.z); // 33

4.通过数组的slice方法

var arr1 = [1, [2, 3], 4];
var arr2 = arr1.slice();

console.log(arr2); // [1, [2, 3], 4]

arr1[0] = 11;
console.log(arr2[0]); // 1; 貌似深拷贝了，但是：

arr1[1][0] = 22;
console.log(arr2); // [1, [22, 3], 4;  还是太年轻啊！！！

5.通过数组的concat方法。

var arr1 = [1, [2, 3], 4];
var arr2 = arr1.concat();

console.log(arr2); //  [1, [2, 3], 4]

arr1[0] = 11;
console.log(arr2[0]); // 1;

arr1[1][0] = 22;
console.log(arr2[1][0]); // 22

1. JSON.stringify() + JSON.parse();

var obj1 = {
a: 1,
b: 2,
c: {
z: 3
}
};

var obj2 = JSON.parse(JSON.stringify(obj1));
console.log(obj2); // {a: 1, b: 2, c: {z: 3}}
obj1.c.z = 33; console.log(obj2.c.z); // 3

var obj1 = {
a: 1,
b: 'b',
c: [1,2,3],
u: undefined,
s: Symbol('s'),
f: function() {
console.log(123);
}
};

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

console.log(obj2); // {a: 1, b: 'b', c: [1, 2, 3]}

2.递归：

var deepCopy = function(obj) {
if (typeof obj !== 'object') return;
var newObj = obj instanceof Array ? [] : {};
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key];
}
}
return newObj;
}
var obj1 = {
a: 1,
b: 'b',
c: [1,2,3],
u: undefined,
s: Symbol('s'),
f: function() {
console.log(123);
}
};
var obj2 = deepCopy（obj1）

let y = {
a: "z",
[Symbol("z")]: "d"
};

let newY = deepCopy(y);

console.log(newY) // --> {a: "z"}
[Symbol("z")]: "d" 呢？原来 for..in 是无法获取Symbol作为健名的元素的！ 那该怎么办呢？ 我们可以利用 Reflect.ownKeys()来得到包括Symbol在内所有实例的属性，从而可以实现Symbol属性的深拷贝！！！
/**
* S.工具函数
* */
// 判断是否是对象（函数和object,不包括null）
function isObject(obj) {
var type = typeof obj;
return type === 'function' || type === 'object' && !!obj;
}
// Internal function for creating a toString-based type tester. (underscore判断数据类型[object Array] 和 [object Object])- tagTester（'Object'）
function tagTester(name) {
return function(obj) {
};
}
// 判断是否为数据（原生支持）
let isArray = Array.isArray;
/**
* E.工具函数
* */
// 深拷贝
function deepClone(obj) {
let objIsObject = tagTester('Object')(obj);
let objIsArray = isArray(obj);
if (!objIsObject && !objIsArray) return;
let newObj = objIsArray ? [] : {};
if (objIsArray) {
// 如果是数组...
return obj.map((item) => {
return (tagTester('Object')(item) || isArray(item)) ? deepClone(item) : item;
})
}
if (objIsObject) {
// 获取对象的所以key(包括symbol的key)
let ownKeys = Reflect.ownKeys(obj);
for (let i = 0, Len = ownKeys.length; i < Len; i++) {
let key = ownKeys[i];
let curObj = obj[key];
if (tagTester('Object')(curObj) || isArray(curObj)) {
newObj[key] = deepClone(curObj);
} else {
newObj[key] = curObj
}
}
}
return newObj;
}

// test
let obj = {
num: 1,
str: 'string',
nu: null,
un: undefined,
fn: function(a) {
a += 1;
return a;
},
ob: {
x: 1,
y: 2,
z: {
a: 'a',
b: 'b'
}
},
[Symbol('foo')]: 'i am symbol',
arr: [1, 2, 3, [4, 5], {m: 9, n: 8}, function() {return 1}]
};
var newObj = deepClone(obj);

这样一来就真的得到了整个世界了！

posted @ 2019-12-04 23:24  沐浴点阳光  阅读(89)  评论(0编辑  收藏