javascript物件深拷貝
阿新 • • 發佈:2020-09-02
JSON.stringify()以及JSON.parse()
優點:簡易
缺點:使用JSON.stringify()以及JSON.parse()它是不可以拷貝 undefined , function, RegExp 等等型別的
當然對於函式可以使用JSON.stringify()和JSON.parse()的第二個引數進行轉換
function stringifyRep(key, value) { if (typeof value === "function") { return `${value}`; } return value; } function parseRep(key, value) { return eval(value); } var a = { b: () => 1 + 1 } var aa = JSON.parse(JSON.stringify(a, stringifyRep), parseRep)
Object.assign(target, source)
Object.assign({}, obj)
僅可拷貝第一層
擴充套件符 {...obj}
僅可拷貝第一層
陣列中的slice() & concat()
var arr1 = [1,2,3]
var arr2 = arr1.slice() // 方法一
// var arr2 = arr1.concat() //方法二
arr2.push(4)
console.log('arr1:', arr1) // arr1: [1, 2, 3]
console.log('arr2:', arr2) // arr1: [1, 2, 3, 4]
第三方庫
jQuery.extend 和 lodash.cloneDeep
遞迴拷貝——最優解決方案
簡易版遞迴深拷貝
function deepClone(obj) { if(obj === null) return null; if(obj instanceof RegExp) return new RegExp(obj); if(obj instanceof Date) return new Date(obj); if(typeof obj !== 'object') { return obj; } let t = new obj.constructor(); for(let key in obj) { t[key] = deepClone(obj[key]); } return t; }
vuex中的深拷貝程式碼
vuex中深拷貝程式碼考慮了迴圈引用等多種問題,更加完善,且寫的簡明,學習一下:
https://github.com/vuejs/vuex/blob/dev/src/util.js#L22
export function find (list, f) {
return list.filter(f)[0]
}
/**
* 深拷貝傳入的物件:
* 快取所有巢狀物件和它們的拷貝物件。
* 如果傳入物件為迴圈引用結構,利用快取過的拷貝避免無限迴圈。
*
* @param {*} obj
* @param {Array<Object>} cache
* @return {*}
*/
export function deepCopy (obj, cache = []) {
// just return if obj is immutable value
if (obj === null || typeof obj !== 'object') {
return obj
}
// 檢測obj是否是迴圈引用結構,是的話直接返回它的拷貝物件
const hit = find(cache, c => c.original === obj)
if (hit) {
return hit.copy
}
const copy = Array.isArray(obj) ? [] : {}
// 首先將copy放入cache, 因為我們需要在遞迴deepCopy的時候引用它
cache.push({
original: obj,
copy
})
Object.keys(obj).forEach(key => {
copy[key] = deepCopy(obj[key], cache)
})
return copy
}