提前熟知:
var a = 1;
var b = a;
console.log(b) // 1
a = 2;
console.log(b) // 1
b = 3;
console.log(a) // 2
let a2 = { a:1, b:'Trist' };
let b2 = a2;
console.log(b2) // {a: 1, b: "Trist"}
b2.a = 2;
console.log(a2.a) // 2
注:深浅拷贝只针对于引用数据类型
function clone(obj) {
var cloneObj = {};
for(var key of Object.keys(obj)) {
cloneObj[key] = obj[key];
}
return cloneObj;
}
var a3 = {
a: 1,
b: 'Trist',
c: { d: 1 }
}
var b3 = clone(a3)
console.log(b3) // {a: 1,b: "Trist",c: {d: 1}}
a3.a = 2;
console.log(b3.a) // 1
b3.b = '张三',
console.log(a3.b) // Trist
b3.c.d = 2;
console.log(a3.c.d) // 2
注:通过对浅拷贝的认识,如果我们要实现对更深层级的数据不仅是单纯的引用,则需要对原对象内所有的属性值进行遍历递归,这就是我们的深拷贝了
function deepClone(obj, cloneObj) {
var cloneObj = cloneObj || {};
for(var i in obj) {
// 通过遍历判断属性是否为引用类型,此处注意null因为历史遗留bug通过typeof输出为object
if(typeof obj[i] === 'object' && typeof obj[i] !== null) {
// 判断引用值是否为数据 obj[i] instanceof Array
cloneObj[i] = (obj[i].constructor === Array) ? [] : {};
// 进行递归
deepClone(obj[i], cloneObj[i]);
}else {
cloneObj[i] = obj[i];
}
}
return cloneObj;
}
var b4 = deepClone(a4,b4);
console.log(b4)
a4.a = 2;
console.log(b4.a) // 1
b4.b = '张三',
console.log(a4.b) // Trist
console.log(a4.c) // 1
console.log(b4.c) // 1
b4.c.d = 2;
console.log(a4.c) // 1
console.log(b4.c) // 2
console.log(a4.size) // [1, 2, 3]
console.log(b5.size) // [1, 2, 3]
b5.size.push(4,5,6)
console.log(a4.size) // [1, 2, 3]
console.log(b5.size) // [1, 2, 3, 4, 5, 6]
Object.assign() 拷贝的是属性值,只实现了对第一层的深拷贝,而不能进行更深层的深拷贝,所以归根结底属于浅拷贝
var assign1 = Object.assign({}, a4);
console.log(assign1); // {a: 2, b: "Trist", c: {d: 1}, size: (3) [1, 2, 3]}
了解即可
function simpleClone(obj) {
var copy = Object.create(Object.getPrototypeOf(obj));
Object.getOwnPropertyNames(obj).forEach(key => {
var desc = Object.getOwnPropertyDescriptor(obj, key);
Object.defineProperty(copy, key, desc);
})
return copy;
}
var es5 = simpleClone(a3);
console.log(es5) // {a: 2, b: "Trist", c: {d: 1}}
下面这种是封装比较好的原生深拷贝写法:
function deepClone3(obj) {
if(obj === null ) return null;
if(typeof obj !== 'object') return obj;
if(obj.constructor === Date) return new Date(obj);
var newObj = new obj.constructor();
for(var key in obj) {
if(obj.hasOwnProperty(key)) {
var val = obj[key];
newObj[key] = typeof val === 'object' ? arguments.callee(val) : val;
}
}
return newObj;
}
var bbb = deepClone3(a4);
console.log(bbb); // {a: 2, b: "Trist", c: {d: 1}, size: (3) [1, 2, 3]}
仅能处理Number, String, Boolean, Array 这种扁平对象,也即是能被JSON直接表示的数据结构类型
function JSONClone(obj) {
return JSON.parse(JSON.stringify(obj))
}
var json = JSONClone(a4);
console.log(json) // {a: 2, b: "Trist", c: {d: 1}, size: (3) [1, 2, 3]}
注意引入第三方库
<script src="jquery-3.3.1.min.js"></script>
var jquery1 = $.extend(true, {}, a4);
console.log(jquery1); // {a: 2, b: "Trist", c: {d: 1}, size: (3) [1, 2, 3]}
注意引入第三方库
<script src="lodash.min.js"></script>
var lodash1 = _.cloneDeep(a4);
console.log(lodash1); // {a: 2, b: "Trist", c: {d: 1}, size: (3) [1, 2, 3]}