作者: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 = value
return 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)
// }
// }
// Object
for (let i in value) {
result[i] = deepCopy(value[i])
}
// Promise Function todo:需进行拷贝
if (typeof value === 'function') {
result = value
}
// Symbol
// default case
return 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 = 4
objects.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 = 2
objects?.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 } = target
return new target.constructor(source, flags)
}
new RegExp('', '')
let a = /aaa/g
// TODO: Error:SyntaxError: Function statements require a function name
const handleFun = (target) => {
// 处理箭头函数
if(!target.prototype) return target
//
const body = target.toString()
return new Function(body)
}
const handleNotTraverse = (target, tag) => {
const Ctor = target.constructor
switch(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 cloneTarget
if(canTraverse[type]) {
// 保留原型链的处理
let ctor = target.constructor
cloneTarget = 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))
})
}
// 处理数组、对象、Arguments
for(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 result
if (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])
作者:
作者: