Skip to content

Instantly share code, notes, and snippets.

@westc
Last active October 23, 2018 03:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save westc/b5e7220ea1e0f03bd2893b5e38de4bbb to your computer and use it in GitHub Desktop.
Save westc/b5e7220ea1e0f03bd2893b5e38de4bbb to your computer and use it in GitHub Desktop.
Mimic a specified array or object while removing recursive structures.
function mimic(obj, opt_filter, opt_maxPathLength) {
function recurse(obj, ancestors, path) {
ancestors = ancestors.concat([obj]);
if (path.length > opt_maxPathLength) {
var e = new Error('Maximum path length exceeded.');
e.path = path;
e.root = obj;
throw e;
}
var isArray = Object.prototype.toString.call(obj) === '[object Array]';
var result = isArray ? [] : {};
var keys = [];
if (isArray) {
result.length = obj.length;
for (var i = 0, l = obj.length; i < l; i++) {
if (i in obj) {
keys.push(i);
}
}
}
else {
for (var k in obj) {
keys.push(k);
}
}
for (var haveValue, k, v, i = keys.length; i--; ) {
try {
v = obj[k = keys[i]];
haveValue = true;
} catch (e) {}
if (haveValue && (!opt_filter || opt_filter(v, k, path))) {
if (v !== null && 'object' === typeof v) {
for (var ancestor, j = ancestors.length; j-- && (ancestor = ancestors[j]) !== v; );
if (j < 0) {
result[k] = recurse(v, ancestors, path.concat([k]));
}
}
else {
result[k] = v;
}
haveValue = false;
}
}
return result;
}
opt_maxPathLength = +opt_maxPathLength >= 0 ? +opt_maxPathLength : 20;
return recurse(obj, [], []);
}
var o = {d: 3, a: [1,2,[3,4]], o: 2};
o.a[2].push(o);
console.log(mimic(o));
console.log(mimic(window, x => !(x instanceof Node || x instanceof Function)));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment