Skip to content

Instantly share code, notes, and snippets.

@yantze
Last active June 16, 2018 12:57
Show Gist options
  • Save yantze/c428dd022c0c85db2d14c37da4c1dec0 to your computer and use it in GitHub Desktop.
Save yantze/c428dd022c0c85db2d14c37da4c1dec0 to your computer and use it in GitHub Desktop.
deep copy a object
/*
* https://gist.github.com/yantze/c428dd022c0c85db2d14c37da4c1dec0
* https://github.com/pvorb/clone/blob/master/clone.js#L74:8
* author: yantze
* typeoof
* 对象为 function ,可能是 Function, class, Symbol, 不复制,因为这些是非结构化对象,但可以生成实例
* 对象为 object, 可能是 Date 实例, class 实例,{}, [], Regex 实例, Buffer 实例, 错误实例
*/
function deepCopy(obj) {
let map = new WeakMap()
function __objToStr(o) {
return Object.prototype.toString(o)
}
function _clone(obj) {
if (obj === null || obj === undefined || typeof obj === 'function') {
return obj
}
let existobj = map.get(obj)
//如果这个对象已经被记录则直接返回
if(existobj) {
return existobj
}
let child
let proto
if (typeof obj === 'object' && Array.isArray(obj)) {
child = []
}
if (typeof obj === 'object' && __objToStr(obj) === '[object RegExp]') {
child = new RegExp(obj.source) // 缺少 flags
return child
}
if (typeof obj === 'object' && __objToStr(obj) === '[object Date]') {
child = new Date(obj)
return child
}
if (typeof obj === 'object' && __objToStr(obj) === '[object Number]') {
child = new Number(obj)
return child
}
if (typeof obj === 'object' && __objToStr(obj) === '[object Boolean]') {
child = new Boolean(obj)
return child
}
if (typeof obj === 'object' && __objToStr(obj) === '[object String]') {
child = new String(obj)
return child
}
if (typeof obj === 'object' && __objToStr(obj) === '[object Symbol]') {
child = new Symbol(obj)
return child
}
if (typeof obj === 'object' && typeof Buffer !== 'undefined' && Buffer.isBuffer(a)) { // nodejs
child = new Buffer(obj)
return child
}
if (typeof obj === 'string') {
return obj
}
if (typeof obj === 'number') {
return obj
}
// Uint8Array, Uint16Array, Uint32Array, BufferArray
if (child === undefined) {
proto = Object.getPrototypeOf(obj)
child = Object.create(proto)
}
map.set(obj, child)
for (let i in obj) {
// if (proto) {
// let attr = Object.getPrototypeOf(obj, i)
// if (attr && attr.set == null) continue
// }
child[i] = _clone(obj[i])
}
return child
}
return _clone(obj)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment