分享 4 種 JS 深拷貝的方法

來源 | https://www.fly63.com/
淺拷貝與深拷貝
深拷貝是將一個對象從內(nèi)存中完整的拷貝一份出來,從堆內(nèi)存中開辟一個新的區(qū)域存放新對象,且修改新對象不會影響原對象。
1、JSON.parse(JSON.stringify(obj))
let a = {a:1,b:2}let b = JSON.parse(JSON.stringify(a))a.a = 11console.log(a)//{a:1,b:2}console.log(b)//{a:11,b:2}
1.1 JSON.parse(JSON.stringify(obj))深淺拷貝的缺陷
let a = {name: 'Jack',age: 18,hobbit: ['sing', {type: 'sports', value: 'run'}],score: {math: 'A',},run: function() {},walk: undefined,fly: NaN,cy: null,date: new Date()}let b = JSON.parse(JSON.stringify(a))console.log(b)// {// age: 18,// cy: null,// date: "2022-05-15T08:04:06.808Z"// fly: null,// hobbit: (3) ["dance", "sing", {…}],// name: "Jack",// score: {math: "A"},// }
取不到值為 undefined 的 key;如果對象里有函數(shù),函數(shù)無法被拷貝下來;無法拷貝copyObj對象原型鏈上的屬性和方法;對象轉(zhuǎn)變?yōu)?date 字符串。
2、普通遞歸函數(shù)實現(xiàn)深拷貝
function deepClone(source) {if (typeof source !== 'object' || source == null) {return source;}const target = Array.isArray(source) ? [] : {};for (const key in source) {if (Object.prototype.hasOwnProperty.call(source, key)) {if (typeof source[key] === 'object' && source[key] !== null) {target[key] = deepClone(source[key]);} else {target[key] = source[key];}}}return target;}
2.1、解決循環(huán)引用和symblo類型
function cloneDeep(source, hash = new WeakMap()) {if (typeof source !== 'object' || source === null) {return source;}if (hash.has(source)) {return hash.get(source);}const target = Array.isArray(source) ? [] : {};Reflect.ownKeys(source).forEach(key => {const val = source[key];if (typeof val === 'object' && val != null) {target[key] = cloneDeep(val, hash);} else {target[key] = val;}})return target;}
3、兼容多種數(shù)據(jù)類型
const deepClone = (source, cache) => {if(!cache){cache = new Map()}if(source instanceof Object) { // 不考慮跨 iframeif(cache.get(source)) { return cache.get(source) }let resultif(source instanceof Function) {if(source.prototype) { // 有 prototype 就是普通函數(shù)result = function(){ return source.apply(this, arguments) }} else {result = (...args) => { return source.call(undefined, ...args) }}} else if(source instanceof Array) {result = []} else if(source instanceof Date) {result = new Date(source - 0)} else if(source instanceof RegExp) {result = new RegExp(source.source, source.flags)} else {result = {}}cache.set(source, result)for(let key in source) {if(source.hasOwnProperty(key)){result[key] = deepClone(source[key], cache)}}return result} else {return source}}
4、jquery.extend()方法
可以使用$.extend進行深拷貝$.extend(deepCopy, target, object1, [objectN])//第一個參數(shù)為true,就是深拷貝let a = {a: 1,b: { d:8},c: [1, 2, 3]};let b = $.extend(true, {}, a);console.log(a.b.d === b.b.d); // false
4.1、 jQuery.extend 源碼
jQuery.extend = jQuery.fn.extend = function() {var options,name,src,copy,copyIsArray,clone,target = arguments[0] || {},i = 1,length = arguments.length,deep = false;// Handle a deep copy situationif (typeof target === "boolean") {deep = target;// Skip the boolean and the targettarget = arguments[i] || {};i++;}// Handle case when target is a string or something (possible in deep copy)if (typeof target !== "object" && !jQuery.isFunction(target)) {target = {};}
總結(jié)
以上就是我今天跟你分享的4個關(guān)于JavaScript深拷貝的方法,希望對你有幫助。
學(xué)習(xí)更多技能
請點擊下方公眾號
![]()
評論
圖片
表情
