Skip to content

Instantly share code, notes, and snippets.

@bprosnitz
Last active March 10, 2016 06:52
Show Gist options
  • Save bprosnitz/cf1d1a3dd1008eef5a85 to your computer and use it in GitHub Desktop.
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
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