假设我们有一个这样的需求,我们需要编辑修改一份表单,修改后提交之前想还原到之前的表单的值,这样我们就需要对原始表单有一个备份
// 原始表单
var form = {
name: '张三',
age: 18,
sex: 1,
score:{
math: 99,
chinese: 80,
english: 90
}
}
1.直接复制
// 备份一份表单
var formBank = form
// 然后我们现在要修改form的sex
form.sex = 0
console.log(formBank.sex) // 0
// 很显然这样子formBank的sex也会变成0
// 因为formBank是指向了form对象的引用
2.取值赋值
//那我们使用取值赋值的方式来试试
function copy(sub, sup) {
for (var key in sup) {
sub[key] = sup[key];
}
}
var formCopy = {}
copy(formCopy, form)
//这样我们就通过取值赋值的方式得到了一个新的对象
//同样我们来修改一下form.age
form.age = 20
console.log(formCopy.age) // 20
//新的对象formCopy似乎不会被form对象影响
//我们再修改score.math试试
form.score.math = 100
console.log(formCopy.math) // 100
// 好像不行,因为实际上这个情况是跟上一个方式一样的,
// formCopy.score的指向就是form.score对象引用
3.通过JSON的parse 和 stringify转换
// 先将form对象转换成json字符串再转换会对象,这样就不会copy出来的对象就不会指到form的引用了
var formParse = JSON.parse(JSON.stringify(form))
form.name = '李四'
console.log(formParse.name) // 张三
form.score.chinese = 88
console.log(formParse.score.chinese) // 80
假如我们是处理一般的后台请求过来的数据的话使用这个方法应该是最快捷方便的,但是我们假设给form添加这样一个属性
form.func = function(){
console.log('this is a function')
}
// 在通过JSON的parse和stringify转换会怎么样呢
// 我们先看看JSON.stringify(form)
console.log(JSON.stringify(form)
//{"name":"李四","age":19,"sex":0,"score":{"math":99,"chinese":80,"english":90}}
//很明显这样并不能达到我们想要的效果,转换成字符串后func不见了这样再转换成对象的话也是一样的
4.深度拷贝
其实我们在第二种方法的时候就可以解决这个问题了,我们只要通过递归把对象取值赋值到底即可
function deepCopy (sub, sup) {
for (var key in sup) {
if (typeof sup[key] === 'object') {
sub[key] = {};
if(sup[key].length) {
sub[key] = []
}
deepCopy (sub[key], sup[key]);
} else {
sub[key] = sup[key];
}
}
}
//我们给form添加一些属性进行测试看看效果
form.func = function() {
console.log('this is a function')
}
form.arr = [1, 2, 3]
var formDeepCopy = {}
deepCopy(formDeepCopy, form)
console.log(formDeepCopy)
/***
{
age: 19, arr: [1, 2, 3]
func: function() {
console.log('this is a function')
},
name: '李四',
score: {math: 100, chinese: 80, english: 90},
sex: 0
}
***/