分享 4 种 JS 深拷贝的方法

来源 | https://www.fly63.com/
浅拷贝与深拷贝
深拷贝是将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象。
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;如果对象里有函数,函数无法被拷贝下来;无法拷贝copyObj对象原型链上的属性和方法;对象转变为 date 字符串。
2、普通递归函数实现深拷贝
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、解决循环引用和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、兼容多种数据类型
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 就是普通函数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])//第一个参数为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 = {};}
总结
以上就是我今天跟你分享的4个关于JavaScript深拷贝的方法,希望对你有帮助。
学习更多技能
请点击下方公众号
![]()
评论
