js實現淺拷貝和深拷貝
阿新 • • 發佈:2018-08-22
擴展運算 復制對象 數據類型 對象 return strong key stringify 循環
淺拷貝和深拷貝都只針對於像Object, Array這樣的復雜對象,
區別:淺拷貝只復制對象的第一層屬性、深拷貝可以對對象的屬性進行遞歸復制
如果數組元素是基本類型,就會拷貝一份,互不影響,而如果是對象或者數組,就會只拷貝對象和數組的引用,這樣我們無論在新舊數組進行了修改,兩者都會發生變化,這種叫淺拷貝。
深拷貝就是指完全的拷貝一個對象,即使嵌套了對象,兩者也相互分離,修改一個對象的屬性,也不會影響另一個。
一、淺拷貝
1、數組的淺拷貝
(1)、可用concat、slice返回一個新數組的特性來實現拷貝
var arr = [‘old‘, 1, true, null, undefined];var new_arr = arr.concat(); // 或者var new_arr = arr.slice()也是一樣的效果; new_arr[0] = ‘new‘; console.log(arr); // ["old", 1, true, null, undefined] console.log(new_arr); // ["new", 1, true, null, undefined]/2、
(2)、還有for循環也能實現數組的淺拷貝
var arr = [1,2,3,4,5] var arr2 = copyArr(arr) function copyArr(arr) { let res= [] for (let i = 0; i < arr.length; i++) { res.push(arr[i]) } return res }
(3)、ES6擴展運算符實現數組的淺拷貝
var arr = [1,2,3,4,5] var [ ...arr2 ] = arr arr[2] = 5 console.log(arr) console.log(arr2)
但是如果數組嵌套了對象或者數組的話用concat、slice拷貝只要有修改會引起新舊數組都一起改變了,比如:
var arr = [{old: ‘old‘}, [‘old‘]];var new_arr = arr.concat(); arr[0].old = ‘new‘; new_arr[1][0] = ‘new‘; console.log(arr); // [{old: ‘new‘}, [‘new‘]] console.log(new_arr); // [{old: ‘new‘}, [‘new‘]]
2、對象的淺拷貝
(1)、萬能的for循環
var obj = { name: ‘FungLeo‘, sex: ‘man‘, old: ‘18‘ } var obj2 = copyObj(obj) function copyObj(obj){ let res = {} for (var key in obj) { res[key] = obj[key] } return res }
(2)、ES6擴展運算符實現對象的淺拷貝
var obj = { name: ‘FungLeo‘, sex: ‘man‘, old: ‘18‘ } var { ...obj2 } = obj obj.old = ‘22‘ console.log(obj) console.log(obj2)
同樣如果對象裏面還嵌套其他引入數據類型,對象的淺拷貝也無法做到真正的拷貝深層的東西
Object.assign()也可以對數組、對象實現淺拷貝
下面是淺拷貝一個通用方法,實現思路:遍歷對象,把屬性和屬性值都放在一個新的對象裏
var shallowCopy = function (obj) { // 只拷貝對象 if (typeof obj !== ‘object‘) return; // 根據obj的類型判斷是新建一個數組還是一個對象 var newObj = obj instanceof Array ? [] : {}; // 遍歷obj,並且判斷是obj的屬性才拷貝 for (var key in obj) { if (obj.hasOwnProperty(key)) { newObj[key] = obj[key]; } } return newObj; }
二、深拷貝
下面是深拷貝一個通用方法,實現思路:拷貝的時候判斷屬性值的類型,如果是對象,繼續遞歸調用深拷貝函數
var deepCopy = function(obj) { // 只拷貝對象 if (typeof obj !== ‘object‘) return; // 根據obj的類型判斷是新建一個數組還是一個對象 var newObj = obj instanceof Array ? [] : {}; for (var key in obj) { // 遍歷obj,並且判斷是obj的屬性才拷貝 if (obj.hasOwnProperty(key)) { // 判斷屬性值的類型,如果是對象遞歸調用深拷貝 newObj[key] = typeof obj[key] === ‘object‘ ? deepCopy(obj[key]) : obj[key]; } } return newObj; }
還有一種比較實用的深拷貝技巧:
function deepcopy(obj){ return JSON.parse(JSON.stringify(obj)); }
但這種方法會存在一些缺陷,比如無法處理function,無法處理Reg,無法處理循環引用對象,但一般來說是夠用的
js實現淺拷貝和深拷貝