Last active
March 10, 2016 06:52
-
-
Save bprosnitz/cf1d1a3dd1008eef5a85 to your computer and use it in GitHub Desktop.
Generate javascript code that will create a clone of a given javascript object
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function buildValMap(obj, m) { | |
if (typeof obj !== 'object' || obj === null) { | |
return ''; | |
} | |
if (obj === Object.prototype || obj === Array.prototype) { | |
return ''; | |
} | |
if (m.has(obj)) { | |
return ''; | |
} | |
var num = m.size; | |
m.set(obj, num); | |
if (obj instanceof Uint8Array) { | |
return 'var v' + num + '=new Uint8Array([' + obj.toString() + ']);\n'; | |
} | |
var str = ''; | |
str += buildValMap(Object.getPrototypeOf(obj), m); | |
var keys = Object.getOwnPropertyNames(obj); | |
for (var k in keys) { | |
var key = keys[k]; | |
var val = obj[key]; | |
str += buildValMap(val, m); | |
} | |
if (Array.isArray(obj)) { | |
str += 'var v' + num + '=[];\n'; | |
} else { | |
if (Object.getPrototypeOf(obj) !== Object.prototype) { | |
var prototypeRef = 'v' + m.get(Object.getPrototypeOf(obj)); | |
str += 'var v' + num + '=Object.create(' + prototypeRef + ');\n'; | |
} else { | |
str += 'var v' + num + '=Object.create(Object.prototype);\n'; | |
} | |
} | |
return str; | |
} | |
function stringifyPrimitive(v) { | |
if (typeof v === 'string') { | |
return '\'' + v + '\''; | |
} else { | |
return '' + v; | |
} | |
} | |
function buildObjectInternal(obj, m) { | |
if (obj === Object.prototype || obj === Array.prototype) { | |
return ''; | |
} | |
if (obj === Uint8Array) { | |
return ''; | |
} | |
if (Array.isArray(obj)) { | |
var arrStr = 'v' + m.get(obj) + '=['; | |
var isFirst = true; | |
obj.forEach(function(val) { | |
if (isFirst) { | |
isFirst = false; | |
} else { | |
arrStr += ','; | |
} | |
if (typeof val === 'object' && val !== null) { | |
arrStr += 'v'+m.get(val); | |
} else { | |
arrStr += stringifyPrimitive(val); | |
} | |
}); | |
arrStr += '];\n'; | |
return arrStr; | |
} | |
var str = ''; | |
var keys = Object.getOwnPropertyNames(obj); | |
for (var k in keys) { | |
var key = keys[k]; | |
var desc = Object.getOwnPropertyDescriptor(obj, key); | |
str += 'Object.defineProperty(v' + m.get(obj) + ',\'' + key + '\',{'; | |
str += 'configurable:' + desc.configurable + ','; | |
str += 'enumerable:' + desc.enumerable + ','; | |
str += 'writable:' + desc.writable + ','; | |
if (typeof desc.value === 'object') { | |
str += 'value:v' + m.get(desc.value); | |
} else { | |
str += 'value:' + stringifyPrimitive(desc.value); | |
} | |
str += '});\n'; | |
} | |
return str; | |
} | |
function cloneObjectString(obj) { | |
var str = '(function() {'; | |
var m = new Map(); | |
str += buildValMap(obj, m); | |
m.forEach(function(num, o) { | |
str += buildObjectInternal(o, m); | |
}); | |
return str + 'return v' + m.get(obj) + ';\n})()'; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment