Skip to content

Instantly share code, notes, and snippets.

@BodhiHu
Last active January 3, 2016 05:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save BodhiHu/7594cafbfab682f790eb to your computer and use it in GitHub Desktop.
Save BodhiHu/7594cafbfab682f790eb to your computer and use it in GitHub Desktop.
Deep clone an JS object: non recursive way. This originally is a fix of the famous.utilities.Utility.clone method (https://github.com/SeanOceanHu/famous/blob/develop/src/utilities/Utility.js#L115), which could easily cause call stack overflow)
/*
* Trampoline to avoid recursion in JS, see:
* http://www.integralist.co.uk/posts/js-recursion.html
*/
function trampoline() {
var func = arguments[0];
var args = [];
for (var i = 1; i < arguments.length; i++) {
args[i - 1] = arguments[i];
}
var currentBatch = func.apply(this, args);
var nextBatch = [];
while (currentBatch && currentBatch.length > 0) {
currentBatch.forEach(function(eachFunc) {
var ret = eachFunc();
if (ret && ret.length > 0) {
nextBatch = nextBatch.concat(ret);
}
});
currentBatch = nextBatch;
nextBatch = [];
}
};
/*
* Deep clone an object using the trampoline technique.
*
* @param target {Object} Object to clone
* @return {Object} Cloned object.
*/
function clone(target) {
if (typeof target !== 'object') {
return target;
}
if (target == null || Object.keys(target).length == 0) {
return target;
}
function _clone(b, a) {
var nextBatch = [];
for (var key in b) {
if (typeof b[key] === 'object' && b[key] !== null) {
if (b[key] instanceof Array) {
a[key] = [];
}
else {
a[key] = {};
}
nextBatch.push(_clone.bind(null, b[key], a[key]));
}
else {
a[key] = b[key];
}
}
return nextBatch;
};
var ret = target instanceof Array ? [] : {};
(trampoline.bind(null, _clone))(target, ret);
return ret;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment