1.使用递归
function deepClone(obj) {
if (obj === null || typeof obj !== 'object') {
return obj;
}
var clone = Array.isArray(obj) ? [] : {};
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
clone[key] = deepClone(obj[key]);
}
}
return clone;
}
var originalObject = { key1: 'value1', nestedObj: { nestedKey: 'nestedValue' } };
var deepCopy = deepClone(originalObject);
console.log(deepCopy.nestedObj === originalObject.nestedObj); // 输出 false
2. 使用 JSON 序列化和反序列化
var originalObject = { key1: 'value1', nestedObj: { nestedKey: 'nestedValue' } };
// 利用 JSON 进行深拷贝
var deepCopy = JSON.parse(JSON.stringify(originalObject));
console.log(deepCopy.nestedObj === originalObject.nestedObj); // 输出 false
使用 JSON 序列化和反序列化的方法有一些限制:
1.它无法处理包含循环引用的对象。
JSON 序列化和反序列化无法处理包含循环引用的对象。当对象中存在循环引用时,JSON.stringify() 会抛出异常,因为 JSON 不支持循环引用的结构。
var obj = { prop1: 'value1' };
obj.prop2 = obj; // 创建循环引用
// 尝试使用 JSON.stringify() 序列化包含循环引用的对象
try {
var serialized = JSON.stringify(obj);
} catch (error) {
console.error(error.message); // 输出 "Converting circular structure to JSON"
}
2.它会忽略 undefined、函数、正则表达式等特殊类型的属性。
JSON 格式规范定义了一组数据类型,其中并没有包括 JavaScript 中的一些特殊类型,比如 undefined、函数(functions)和正则表达式(regular expressions)。因此,当使用 JSON 序列化和反序列化时,这些特殊类型的属性会被忽略。
(1)忽略 undefined 属性
var obj = { key1: 'value1', key2: undefined };
var serialized = JSON.stringify(obj);
console.log(serialized); // 输出 {"key1":"value1"}
(2)忽略函数属性
var obj = { key1: 'value1', key2: function() {} };
var serialized = JSON.stringify(obj);
console.log(serialized); // 输出 {"key1":"value1"}
(3)忽略正则表达式属性
var obj = { key1: 'value1', key2: /pattern/ };
var serialized = JSON.stringify(obj);
console.log(serialized); // 输出 {"key1":"value1"}
- List item
3.对于 Date 对象,会变成字符串而不是新的 Date 对象。
原因是使用 JSON 序列化和反序列化不能完全拷贝 Date 对象的原因是因为 JSON 格式对于日期对象处理的方式有限,并且将日期对象序列化为字符串而不是原始的 Date 对象。
3. 使用第三方库
有一些第三方库(如 lodash、underscore 等)提供了深拷贝的函数,它们通常更健壮且可以处理更多的特殊情况。例如,使用 lodash 的 cloneDeep
var _ = require('lodash');
var originalObject = { key1: 'value1', nestedObj: { nestedKey: 'nestedValue' } };
var deepCopy = _.cloneDeep(originalObject);
console.log(deepCopy.nestedObj === originalObject.nestedObj); // 输出 false