作者:xl
// map 处理循环拷贝function clone(origin, map = new Map()) {if (typeof origin !== 'object' || origin === null) {return origin;}if (map.get(origin)) {return map.get(origin);}let obj = {}if (Object.prototype.toString.call(origin) === '[object Array]') {obj = []}map.set(origin, obj);for (const key in origin) {obj[key] = clone(origin[key], map);}return obj;}
作者:gochri
/*String、Array、TypedArray、Map 和 Set 都是内置可迭代对象,因为它们的原型对象都拥有一个 Symbol.iterator 方法。Object.entries()方法返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 for...in 循环遍历该对象时返回的顺序一致(区别在于 for-in 循环还会枚举原型链中的属性)。*/// todo: 处理循环引用function isObject(value) {var type = typeof value;return value != null && (type == 'object' || type == 'function');}var deepCopy = (value) => {let result = {}if (!isObject(value)) {result = valuereturn result}if (Array.isArray(value)) {result = new Array()for (let i in value) {result[i] = deepCopy(value[i])}return result}if (value instanceof Map) {result = new Map()for (let [k, v] of value) {result.set(k, deepCopy(v))}// return result}if (value instanceof Set) {result = new Set()for (let v of value) {result.add(deepCopy(v))}// return result}// Object no iterator// if (typeof value[Symbol.iterator] === 'function') {// for (const [k, v] of Object.entries(value)) {// result[k] = deepCopy(v)// }// }// Objectfor (let i in value) {result[i] = deepCopy(value[i])}// Promise Function todo:需进行拷贝if (typeof value === 'function') {result = value}// Symbol// default casereturn result}// ------------- TestCode ----------// var objects = new Set([1, 2, 3])// var objects = [1, 2, 3]var objects = new Map()objects.set('c', 5)objects.set('d', 6)objects.a = 4objects.b = function () {return new Promise((resolve, reject) => {if (this.a) {resolve(this.a)} else {reject('no this a')}})}// objects.__proto__.logA = () => { console.log('a', a) }var shallow = deepCopy(objects);objects.a = 2objects?.b()?.then(r => console.log(r)).catch(err => console.log(err))shallow?.b()?.then(r => console.log(r)).catch(err => console.log(err))console.log(shallow, shallow === objects);// => result// Map(2) { 'c' => 5, 'd' => 6, a: 4, b: [Function (anonymous)] } false// 2// 4
作者:奥兰度
let a = new Map()let b = {a}// 首先解决循环引用,代码结构,考虑特殊数据结构,比如包装对象,比如正则、函数、日期等等const isObject = (target) => (typeof target === 'object' || typeof target === 'function') && target !== null// 判断特殊对象的方法const getType = (obj) => Object.prototype.toString.call(obj)// 特殊对象类型const canTraverse = {'[object Map]': true,'[object Set]': true,'[object Array]': true,'[object Object]': true,'[object Arguments]': true,}const canNotTraverse = {'[object String]': true,'[object Number]': true,'[object Boolean]': true,'[object RegExp]': true,'[object Date]': true,'[object Error]': true,'[object Function]': true,'[object Symbol]': true,}const mapTag = '[object Map]'const setTag = '[object Set]'// 处理正则const handleRegExp = (target) => {const { source, flags } = targetreturn new target.constructor(source, flags)}new RegExp('', '')let a = /aaa/g// TODO: Error:SyntaxError: Function statements require a function nameconst handleFun = (target) => {// 处理箭头函数if(!target.prototype) return target//const body = target.toString()return new Function(body)}const handleNotTraverse = (target, tag) => {const Ctor = target.constructorswitch(tag) {case boolTag:case numberTag:case stringTag:case errorTag:case dateTag:return new Ctor(target)case regexpTag:return handleRegExp(target)case funcTag:return handleFun(target)default:return new Ctor(target)}}// 解决循环引用,解决 Map 带来的内存溢出问题const deepClone = (target = {}, map = new WeakMap()) => {if(!isObject(target)) {return target}let type = getType(target)let cloneTargetif(canTraverse[type]) {// 保留原型链的处理let ctor = target.constructorcloneTarget = new ctor()} else {handleNotTraverse(target, type)}// 有争议,循环引用的 set 类型并不能很好处理,因为其实是相当于表层浅复制了if(map.get(target)) {return target}map.set(target, true)if(type === mapTag) {target.forEach((item, key) => {cloneTarget.set(deepClone(key, map), deepClone(item, map))})}if(type === setTag){// Set 在 forEach 时,如果你对源 Set 添加东西,会造成爆栈target.forEach((item) => {cloneTarget.add(deepClone(item, map))})}// 处理数组、对象、Argumentsfor(let prop in target) {if(target.hasOwnProperty(prop)) {cloneTarget[prop] = deepClone(target[prop], map)}}return cloneTarget}
作者:安静
function deepClone(obj = {}) {if (typeof obj !== 'object' || obj == null) {// obj 是 null ,或者不是对象和数组,直接返回return obj}// 初始化返回结果let resultif (obj instanceof Array) {result = []} else {result = {}}for (let key in obj) {// 保证 key 不是原型的属性if (obj.hasOwnProperty(key)) {// 递归调用!!!result[key] = deepClone(obj[key])}}// 返回结果return result}const obj1 = {age: 20,name: 'xxx',address: {city: 'beijing'},arr: ['a', 'b', 'c']}const obj2 = deepClone(obj1)obj2.address.city = 'shanghai'obj2.arr[0] = 'a1'console.log(obj1.address.city)console.log(obj1.arr[0])
作者:
作者:
