{"action":"opened","issue":{"url":"https://api.github.com/repos/maixiaojie/maixiaojie.github.io/issues/10","repository_url":"https://api.github.com/repos/maixiaojie/maixiaojie.github.io","labels_url":"https://api.github.com/repos/maixiaojie/maixiaojie.github.io/issues/10/labels{/name}","comments_url":"https://api.github.com/repos/maixiaojie/maixiaojie.github.io/issues/10/comments","events_url":"https://api.github.com/repos/maixiaojie/maixiaojie.github.io/issues/10/events","html_url":"https://github.com/maixiaojie/maixiaojie.github.io/issues/10","id":293792848,"number":10,"title":"[分享]javascript 数组以及对象的深拷贝（复制数组或复制对象）的方法","user":{"login":"maixiaojie","id":11681287,"avatar_url":"https://avatars2.githubusercontent.com/u/11681287?v=4","gravatar_id":"","url":"https://api.github.com/users/maixiaojie","html_url":"https://github.com/maixiaojie","followers_url":"https://api.github.com/users/maixiaojie/followers","following_url":"https://api.github.com/users/maixiaojie/following{/other_user}","gists_url":"https://api.github.com/users/maixiaojie/gists{/gist_id}","starred_url":"https://api.github.com/users/maixiaojie/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/maixiaojie/subscriptions","organizations_url":"https://api.github.com/users/maixiaojie/orgs","repos_url":"https://api.github.com/users/maixiaojie/repos","events_url":"https://api.github.com/users/maixiaojie/events{/privacy}","received_events_url":"https://api.github.com/users/maixiaojie/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2018-02-02T07:06:40Z","updated_at":"2018-02-02T07:06:40Z","closed_at":null,"author_association":"OWNER","body":"## 前言\r\n\r\n在js中，数组和对象的复制如果使用`=`号来进行复制，那只是浅拷贝。如下：\r\n```\r\nlet arr = [1,3,4,5]\r\nlet arr2 = arr\r\n```\r\n \r\n如上，arr的修改，会影响arr2的值，这显然在绝大多数情况下，并不是我们所需要的结果。\r\n\r\n因此，数组以及对象的深拷贝就是javascript的一个基本功了。\r\n\r\n## 数组的深拷贝\r\n\r\n条条大道通罗马，实现数组的深拷贝，是有好几种方法的。举例如下：\r\n\r\n### for循环实现数组的深拷贝\r\n\r\nfor循环是非常好用的。如果不知道高级方法，通过for循环能够完成我们大多数的需求。\r\n```\r\nvar arr = [1,2,3,4,5]\r\nvar arr2 = copyArr(arr)\r\nfunction copyArr(arr) {\r\n    let res = []\r\n    for (let i = 0; i < arr.length; i++) {\r\n     res.push(arr[i])\r\n    }\r\n    return res\r\n}\r\n```\r\n\r\n如上，通过对数组的for循环，即可实现对数组的深拷贝了。\r\n\r\n### slice 方法实现数组的深拷贝\r\n\r\n这个代码实现非常简单。原理也比较好理解，他是将原数组中抽离部分出来形成一个新数组。我们只要设置为抽离全部，即可完成数组的深拷贝。代码如下：\r\n```\r\nvar arr = [1,2,3,4,5]\r\nvar arr2 = arr.slice(0)\r\narr[2] = 5\r\nconsole.log(arr)\r\nconsole.log(arr2)\r\n```\r\n\r\n### concat 方法实现数组的深拷贝\r\n这个代码也非常简单，原理更加粗暴。它是用于连接多个数组组成一个新的数组的方法。那么，我们只要连接它自己，即可完成数组的深拷贝。代码如下：\r\n\r\n```\r\nvar arr = [1,2,3,4,5]\r\nvar arr2 = arr.concat()\r\narr[2] = 5\r\nconsole.log(arr)\r\nconsole.log(arr2)\r\n```\r\n\r\n### ES6扩展运算符实现数组的深拷贝\r\nOK，以上之前讲的方法全部过时了，用下面的方法实现数组的深拷贝是最简单的。\r\n```\r\nvar arr = [1,2,3,4,5]\r\nvar [ ...arr2 ] = arr\r\narr[2] = 5\r\nconsole.log(arr)\r\nconsole.log(arr2)\r\n```\r\n\r\n## 对象的深拷贝\r\n\r\n对象的深拷贝相比数组也没有困难许多，列举两个方法。\r\n\r\n### 万能的for循环实现对象的深拷贝\r\n在很多时候，for循环能够解决大问题。\r\n```\r\nvar obj = {\r\n  name: 'FungLeo',\r\n  sex: 'man',\r\n  old: '18'\r\n}\r\nvar obj2 = copyObj(obj)\r\nfunction copyObj(obj) {\r\n  let res = {}\r\n  for (var key in obj) {\r\n    res[key] = obj[key]\r\n  }\r\n  return res\r\n}\r\n```\r\n\r\n### 转换成json再转换成对象实现对象的深拷贝\r\n上面的代码实在是比较长，所以，用一个更暴力的方法吧！代码如下：\r\n```\r\nvar obj = {\r\n  name: 'FungLeo',\r\n  sex: 'man',\r\n  old: '18'\r\n}\r\nvar obj2 = JSON.parse(JSON.stringify(obj))\r\n```\r\n\r\n这个原理没什么好解释的，实在是够简单粗暴的啦！\r\n\r\n### 扩展运算符实现对象的深拷贝\r\n```\r\nvar obj = {\r\n  name: 'FungLeo',\r\n  sex: 'man',\r\n  old: '18'\r\n}\r\nvar { ...obj2 } = obj\r\nobj.old = '22'\r\nconsole.log(obj)\r\nconsole.log(obj2)\r\n```\r\n\r\n\r\n### 小结\r\n数组和对象的深拷贝是js中最常见的应用。理解各种方法是必须的。希望对大家有所帮助。 \r\n\r\n本文中并没有对异常进行处理，主要在讲原理。更多的数组以及对象的操作方法，可以参考`lodash`的源码，查看它的源码可以让你的js基础变得非常牢固。我也在学习中。\r\n\r\n> 使用es6提供的扩展运算符的方法实现深拷贝，简单，高效。并且，对象的深拷贝不会像使用 JSON 方法深拷贝一样，丢失函数等信息，只能用来深拷贝 JSON 数据格式的对象。推荐大家使用。\r\n\r\n补充一个数组去重的方法\r\n```\r\nfunction dedupe(array) {\r\n  return [...new Set(array)]\r\n}\r\nvar arr = [1,2,2,3,3,4,4,5,5]\r\nconsole.log(dedupe(arr))\r\n```\r\n\r\n\r\n"}}
{"actor":{"display_login":"maixiaojie"}}