美文网首页
JS 深拷贝与浅拷贝

JS 深拷贝与浅拷贝

作者: 躺在家里干活 | 来源:发表于2019-09-29 10:22 被阅读0次

引言

要介绍深浅拷贝那么咱们先了解一下js的数据类型。

  • 基本数据类型:number,string,boolean,undefined,null
  • 复杂数据类型:object,array,function,regexp,date 等

一、简介

1.浅拷贝

对于基本数据类型,浅拷贝相当于直接赋值
对于复杂数据类型,浅拷贝只拷贝一层,相当于只拷贝其引用,例如对象B是由对象A浅拷贝得到的,即AB还是指向内存中的同一地址,那么改变对象B,对象A也会改变

2.深拷贝

对于复杂数据类型,深拷贝会拷贝多层,是真正意义上的拷贝,例如对象B是由对象A深拷贝得到的,即AB指向不同的内存地址,那么无论如何改变对象B,对象A也不会改变

二、实现方法

上面讲完什么是深浅拷贝,那么接下来就用具体的代码去实现深浅拷贝

1.浅拷贝

方法一:简直粗暴的直接赋值

var obj1 = { name: 'ming', age: 10 };
var obj2 = obj1;
obj2.name = 'lei';
console.log(obj1.name) // lei
console.log(obj2.name) // lei

方法二:Object.assign(target,source) ES6

Object.assign方法实行的是浅拷贝,而不是深拷贝。如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用,如下面的例子

var obj1 = { name: 'father', children: {name:'son',age:10} };
var obj2 = Object.assign({},obj1)
obj2.children.name = 'lei';
console.log(obj1.children.name) // lei
console.log(obj2.children.name) // lei

方法三:for in 循环

和方法二类似,如果源对象的某个属性是对象,那么目标对象拷贝得到的是这个对象的引用

var obj1 = { name: 'father', children: {name:'son',age:10} };
var obj2 = {};
for (var key in obj1){
    obj2[key] = obj1[key];
}
obj2.children.name = 'lei';
console.log(obj1.children.name) // lei
console.log(obj2.children.name) // lei

方法四:Object.create(target,source);

Object.getOwnPropertyDescriptors 为 ES6 新增方法

var obj1 = { name: 'father', children: {name:'son',age:10} };
var obj2 = Object.create({}, Object.getOwnPropertyDescriptors(obj1));
obj2.children.name = 'lei';
console.log(obj1.children.name) // lei
console.log(obj2.children.name) // lei

2.深拷贝

方法一:JSON.parse(JSON.stringify(source))

用JSON.stringify将源对象(source)转为字符串,再用JSON.parse方法将字符串转为目标对象

注: 此方法只能用作可以转为JSON格式对象,否则JSON.stringify方法将会报错,并且不管原来对象的构造函数是什么拷贝之后都会变为Object

var obj1 = { name: 'ming', age: 10 };
var obj2 = JSON.parse(JSON.stringify(obj1));
obj2.name = 'lei';
console.log(obj1.name) // ming
console.log(obj2.name) // lei

方法二:递归拷贝

function deepClone(obj1, obj2) {
  var obj = obj2 || {};
  for (var i in obj1) {
    var temp = obj1[i]; // 避免相互引用对象导致死循环,如obj1.a = obj1的情况
    if (temp === obj) {
      continue;
    }
    if (typeof temp === 'object') {
      obj[i] = (temp.constructor === Array) ? [] : {};
      arguments.callee(temp, obj[i]);
    } else {
      obj[i] = temp;
    }
  }
  return obj;
}
var obj1 = { name: 'father', children: {name:'son',age:10} };
var obj2 = deepClone(obj1);
obj2.children.name = 'lei';
console.log(obj1.children.name) // son
console.log(obj2.children.name) // lei

方法三:Object.create()

function deepClone(obj1, obj2) {
  var obj = obj2 || {};
  for (var i in obj1) {
    var temp = obj1[i]; // 避免相互引用对象导致死循环,如obj1.a = obj1的情况
    if (temp === obj) {
      continue;
    }
    if (typeof temp === 'object') {
      obj[i] = (temp.constructor === Array) ? [] : Object.create(temp);
    } else {
      obj[i] = temp;
    }
  }
  return obj;
}
var obj1 = { name: 'father', children: {name:'son',age:10} };
var obj2 = deepClone(obj1);
obj2.children.name = 'lei';
console.log(obj1.children.name) // son
console.log(obj2.children.name) // lei

方法四:Object.assign(target,source) ES6

将源对象(source)的所有可枚举属性,复制到目标对象(target)

注: 此方法只能用作对象只有一层的情况

var obj1 = { name: 'ming', age: 10 };
var obj2 = Object.assign({},obj1);
obj2.name = 'lei';
console.log(obj1.name) // ming
console.log(obj2.name) // lei

但是,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用,因此也不能被称为深拷贝

var obj1 = { name: 'father', children: {name:'son',age:10} };
var obj2 = Object.assign({},obj1)
obj2.children.name = 'lei';
console.log(obj1.children.name) // lei
console.log(obj2.children.name) // lei

方法五:for in 循环

注: 此方法只能用作对象只有一层的情况,类似方法三

var obj1 = { name: 'ming',age:10};
var obj2 = {};
for (var key in obj1){
  obj2[key] = obj1[key];
}
obj2.name = 'lei';
console.log(obj1.name) // ming
console.log(obj2.name) // lei

实现浅拷贝的方法还有很多种,但是真正实现深拷贝的方法却很少,所以在拷贝对象时一定要注意

相关文章

  • JS中的深拷贝与浅拷贝

    知乎:js中的深拷贝和浅拷贝? 掘金: js 深拷贝 vs 浅拷贝 前言 首先深拷贝与浅拷贝只针对 Object,...

  • js浅拷贝深拷贝

    js浅拷贝,深拷贝的简单实现 基础数据 浅拷贝 深拷贝

  • 浅拷贝和深拷贝

    本文参考:JavaScript中的浅拷贝和深拷贝js 深拷贝 vs 浅拷贝深入剖析 JavaScript 的深复制...

  • js面试题

    1,js的深拷贝与浅拷贝 如何区分深拷贝与浅拷贝,简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,...

  • JS实现深拷贝、instanceof、判断是否为数组

    JS深拷贝 JS中拷贝对象可以按照拷贝的程度可以分为浅拷贝和深拷贝,有些时候我们需要拷贝之后的对象和拷贝之前的对象...

  • JS中对象的复制

    JS中的对象复制分为两种情况:深拷贝和浅拷贝。深拷贝和浅拷贝的区别在于对数组和对象的拷贝,对它们拷贝时浅拷贝只是拷...

  • 认识js下的浅拷贝与深拷贝

    浅拷贝与深拷贝 首先深拷贝和浅拷贝只针对像 Object, Array 这样的复杂对象的。简单来说,浅拷贝只拷贝一...

  • iOS深拷贝(MutableCopy)与浅拷贝(Copy)的区别

    深拷贝和浅拷贝的概念 iOS中有深拷贝和浅拷贝的概念,那么何为深拷贝何为浅拷贝呢?浅拷贝:浅拷贝并不拷贝对象本身,...

  • Objective-C中的浅拷贝和深拷贝

    Objective-C中的浅拷贝和深拷贝IOS开发之深拷贝与浅拷贝(mutableCopy与Copy)详解iOS ...

  • 深拷贝和浅拷贝

    干货!深拷贝和浅拷贝的区别 深拷贝才是拷贝,浅拷贝就是Retain Copy与Retain的区别 Copy: 根据...

网友评论

      本文标题:JS 深拷贝与浅拷贝

      本文链接:https://www.haomeiwen.com/subject/peiiyctx.html