JavaScript拷贝简述
JavaScript里经常用到 copy,而copy又分深拷贝和 浅拷贝。
shallow copy就是让obj1 直接等于oldObj就可以,但是这样会有个问题,就是当你修改任何一个object的时候,都会对另外一个造成同样的修改,所以一般这种copy必须非常小心。
比如下面操作:
Deep copy就是当你copy之后,修改其中任何一个不会影响另外一个object。
而我们经常在代码实现的时候,常常用到的是深拷贝复杂对象,即拷贝后的对象和原对象是独立开来的,彼此之间的改动不会有影响。
深拷贝之JSON.parse
该方法有个缺点:源对象必须是可以json格式化的。
Deep Copy
//method1 --->Json string化--->
function deepCopy(obj/*: Object*/)/*: Object*/ {
return JSON.parse(JSON.stringify(obj));
}
深拷贝之lodash库
该方法缺点:需要额外引入第三方库
//method2 ---> lodash 的 _.cloneDeep(value) -->改方法缺点:需要额外引入第三方库
var objects = [{ 'a': 1 }, { 'b': 2 }];
var deep = _.cloneDeep(objects);
console.log(deep[0] === objects[0]);
// => false
深拷贝之自己封装
按照自己的方法写个深拷贝,这样就可以不用引入第三方库了。
function deepCopy(obj) {
var isObject = function(value) {
var type = typeof value;
return value !== null && (type === 'object' || type === 'function');
}
if (obj == null || !isObject(obj)) { //不是对象拷贝,直接返回
return obj;
}
let result = Array.isArray(obj) ? [] : {};
for(let key in obj) {
if (obj.hasOwnProperty(key)) { //不拷贝原型链上的对象
if (isObject(obj[key])) { //嵌套对象,递归调用
result[key] = deepCopy(obj[key]);
} else {
result[key] = obj[key];
}
}
}
return result;
}
深拷贝之通用方法
//--->更好的通用方式
module.exports = {
deepCopyIfNeeded,
deepCopy
};
function deepCopyIfNeeded(resource/*obj|array*/, returnSafeRef/*Boolean,default=false*/)/*obj|array*/ {
if (returnSafeRef !== undefined &&
typeof returnSafeRef !== 'boolean') {
throw new Error(`paras:returnSafeRef can be ignored, otherwise, ` +
`must be boolean value\(true, false\)!` +
`\nYour secArg is: ${returnSafeRef}`);
} else if (!returnSafeRef) {
return resource;
}
return deepCopy(resource);
}
function deepCopy(obj) {
var isObject = function(value) {
var type = typeof value;
return value !== null && (type === 'object' || type === 'function');
}
if (obj == null || !isObject(obj)) { //不是对象拷贝,直接返回
return obj;
}
let result = Array.isArray(obj) ? [] : {};
for(let key in obj) {
if (obj.hasOwnProperty(key)) { //不拷贝原型链上的对象
if (isObject(obj[key])) { //嵌套对象,递归调用
result[key] = deepCopy(obj[key]);
} else {
result[key] = obj[key];
}
}
}
return result;
}