Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JavaScript之浅拷贝和深拷贝(assign&create&concat&slice) #9

Open
heyushuo opened this issue Dec 27, 2019 · 0 comments
Open

JavaScript之浅拷贝和深拷贝(assign&create&concat&slice) #9

heyushuo opened this issue Dec 27, 2019 · 0 comments

Comments

@heyushuo
Copy link
Owner

一.什么是浅拷贝和深拷贝

浅复制是指只复制一层对象的属性,不会复制对象中的对象的属性,对象的深复制会复制对象中层层嵌套的对象的属性。(单来说浅复制只复制一层对象的属性,而深复制则递归复制了所有层级。)

全局例子都使用如下对象

var info = {
    name: "heyushuo",
    age: 25,
    arr: [1, 2, 3],
    obj: {
      name: "kebi",
      age: 36
    },
    say: function () {
      console.log("heyushuo");
    },
    reg: new RegExp(/[0-9]/),
    date: new Date()
  };

二.浅复制的实现

2.1 ES6 的 Object.assign

将所有可枚举的属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。如果目标对象中的属性具有相同的键,则属性将被源中的属性覆盖。后来的源的属性将类似地覆盖早先的属性

//实现浅复制
  var target = {};
  Object.assign(target, info);
  target.arr[0] = 100;
  console.log(info.arr[0]); //100
// info中的arr也发生了变化,实现的是浅复制

2.2 ES5 的 Object.create

Object.create 的详细解释

复制对象到当前对象的原型上

 var obj = Object.create(info);
 console.log(obj); //100

如下如所示:

2.3 数组的 concat()和 slice()方法可以实现对数组的浅复制

  1. concat()这个方法会先创建当前数组一个副本,然后将接收到的参数添加到这个副本的末尾,最后返回新构建的数组。(不传参数的情况下,它只是复制当前数组并返回副本。)
  2. slice(),它能够基于当前数组中的一或多个项创建一个新数组。
var newArray = ['a',1,2,{name:'heyushuo'}];
var clone1 = newArray.concat();
var clone2 = newArray.slice(0);
clone1[3].name = "kebi";

console.log(clone2.name) //kebi
console.log(newArray.name) //kebi
//通过上边例子可以看到如上两个方法实现的是浅复制

ES6 提供的扩展运算符实现数组的复制也是浅复制

const a1 = [1, 2];
const a2 = [...a1];

2.4 自己封装一个浅复制方法

function clone(obj){
    if(typeof obj != 'object'){
        return 'need a object';
    }

    var object = obj.constructor === Array?[]:{};
    for(var i in obj){
        object[i] = obj[i];
    }
    return object;
}

clone(info);

三.深复制

3.1 实现深复制最简单的方式

JSON 对象是 ES5 中引入的新的类型(支持的浏览器为 IE8+),JSON 对象 parse 方法可以将 JSON 字符串反序列化成 JS 对象,stringify 方法可以将 JS 对象序列化成 JSON 字符串,借助这两个方法,也可以实现对象的深拷贝。

    /**
   *    大多数情况下,上面的就可以满足要求了,但一些时候,我们需要把函数,
   *    正则等特殊数据类型也考虑在内,或者当前环境不支持JSON时,上面的方法也就不适用了。这时,我们可以通过递归来实现对象的深层复制
   **/
var str = JSON.stringify(info);
  console.log(str);
  console.log(JSON.parse(str));

这个方法的缺点如下图所示

3.2 手写实现深复制的函数

  function deepCopy(obj) {
    if (typeof obj != "object") {
      return "need a object";
    }
    var object = obj.constructor == Array ? [] : {};
    for (var i in obj) {
      //判断是对象还是普通类型
      if (typeof obj[i] == "object") {
        //这里需要判断一下是否是正则RegExp 还是 Date 时间
        if (obj[i].constructor === RegExp || obj[i].constructor === Date) {
          object[i] = obj[i];
        } else {
          object[i] = deepCopy(obj[i]);
        }

      } else {
        object[i] = obj[i];
      }
    }
    return object;
  }

  console.log(deepCopy(info));
  //完全拷贝下来了

通过如上函数实现一个对象的合并

function mergeObj(target,obj) {
    if (typeof obj != "object") {
      return "need a object";
    }
    var object = target;
    for (var i in obj) {
      //判断是对象还是普通类型
      if (typeof obj[i] == "object") {
        //这里需要判断一下是否是正则RegExp 还是 Date 时间
        if (obj[i].constructor === RegExp || obj[i].constructor === Date) {
          object[i] = obj[i];
        } else {
          object[i] = deepCopy(obj[i]);
        }

      } else {
        object[i] = obj[i];
      }
    }
    return object;
  }

var heyushuo = mergeObj({
    a: "sdfsadfsdf",
    name: "2123123"
  }, {
    c: "2323",
    d: "8989",
    name: ["sdf", 23, 123]
  });
  console.log(heyushuo);
//   {
//      a: "sdfsadfsdf",
//      c: "2323",
//      d: "8989",
//      name: ["sdf", 23, 123]
//   }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant