从前有匹马叫代码
心若没有栖息的地方,到哪里都是流浪

在JavaScript分为两种原始值和引用值类型,原始值之间的复制是值对值得复制,而引用类型则是引用对引用的复制;

// 原始值的复制;
let num1 = 1;
let num2 = num1;
num2++;
console.log(num1,num2); // 1,2
// 引用类型的复制;
let joe = {
    name:"joe",
    age:20    
}
let john
= joe; john.name = 'john';
console.log(john
=== joe,joe.name); // true john

如你所见,当我们把joe 赋值给john时实际上并没有完全复制一个新的,就好像是下面这样:

 

图片来自 “现代JavaScript教程” 网站;

 

Object.assign(target,arg1,arg2,...)方法用于将第二个参数及以后所有的对象都合并到第一个对象中,并返回第一个对象;

let user = {
    name:"申屠肆",
    hobbies:{
        first:'JavaScript',
        second:'Node'
    }
}

let user_copy = Object.assign({job:'Web开发'},user,);
user_copy.name = '谢必安';
user_copy.hobbies['third'] = 'Python';

console.log(user_copy.name,user.name);
console.log(user_copy.hobbies,user.hobbies);


//控制台

谢必安 申屠肆
{ first: 'JavaScript', second: 'Node', third: 'Python' } { first: 'JavaScript', second: 'Node', third: 'Python' }

虽然Object.assign可以达到我们想要的效果,但是,可以发现,如果合并的对象的某个键对应的值仍然是对象,则还是会存下对象的引用;

接下来,让我们探寻更进一步的方案

// 采用递归 + JSON对象的方法 来完成深度复制

function deep_clone(source,target = {}) {
    for(let key in source) {

        if(source[key].constructor === Object) {
            target[key] = deep_clone(source[key])
        }else if (source[key].constructor === Array) {
            target[key] = JSON.parse(JSON.stringify(source[key]))
        } else {
            target[key] = source[key];
        }

    }
    return target;
}

让我们来试一下

 

var ball = {
    name:'足球',
    shape:{
        text:'圆形',
        size:40
    },
    abc:[1],
    def:[{user:'谢绝'}]
}

function deep_clone(source,target = {}) {
    for(let key in source) {

        if(source[key].constructor === Object) {
            target[key] = deep_clone(source[key])
        }else if (source[key].constructor === Array) {
            target[key] = JSON.parse(JSON.stringify(source[key]))
        } else {
            target[key] = source[key];
        }

    }
    return target;
}
var ball_copy = deep_clone(ball); ball_copy.shape.text="方形"; ball_copy.abc.push(2); ball_copy.def[0].user = "谢绝-copy"; console.log(ball_copy,ball);

 

 

// 控制台打印
{
  name: '足球',
  shape: { text: '方形', size: 40 },
  abc: [ 1, 2 ],
  def: [ { user: '谢绝-copy' } ]
} {
  name: '足球',
  shape: { text: '圆形', size: 40 },
  abc: [ 1 ],
  def: [ { user: '谢绝' } ]
}

使用该方法需要注意的是,不能有“环形结构”

推荐阅读:《现代JavaScript教程》

 

posted on 2021-02-05 23:18  从前有匹马叫代码  阅读(174)  评论(0编辑  收藏  举报