Skip to content

Instantly share code, notes, and snippets.

@duzun

duzun/clone-es5.js

Forked from jherax/clone.js
Created Jul 8, 2016
Embed
What would you like to do?
JavaScript: clona o extiende un objeto
/**
* Creates a deep copy of an object
* @param {Any} from: Source object to clone
* @param {Object} dest: (Optional) destination object to merge with
* @return {Any} The cloned object
*/
var clone = (function() {
var _toString = Object.prototype.toString;
function _clone (from, dest, objectsCache) {
var prop;
// determines whether @from is a primitive value or a function
if (from === null || typeof from !== "object") return from;
// checks if @from refers to an object created previously
if (_toString.call(from) === "[object Object]") {
if (objectsCache.filter(function (item) {
return item === from;
}).length) return from;
// keeps reference to created objects
objectsCache.push(from);
}
// determines whether @from is an instance of any of the following constructors
if (from.constructor === Date || from.constructor === RegExp || from.constructor === Function ||
from.constructor === String || from.constructor === Number || from.constructor === Boolean) {
return new from.constructor(from);
}
if (from.constructor !== Object && from.constructor !== Array) return from;
// creates a new object and recursively iterates over its properties
dest = dest || new from.constructor();
for (prop in from) {
// TODO: allow overwrite existing properties
dest[prop] = (typeof dest[prop] === "undefined" ?
_clone(from[prop], null, objectsCache) :
dest[prop]);
}
return dest;
}
return function (from, dest) {
var objectsCache = [];
return _clone(from, dest, objectsCache);
};
}());
/**
* Creates a deep copy of an object
* @param {Any} from: Source object to clone
* @param {Object} dest: (Optional) destination object to merge with
* @return {Any} The cloned object
*/
var clone = (() => {
const _toString = Object.prototype.toString;
function _clone(from, dest, objectsCache) {
let prop;
// determines whether @from is a primitive value or a function
if (from === null || typeof from !== 'object') return from;
// checks if @from refers to an object created previously
if (_toString.call(from) === '[object Object]') {
if (objectsCache.filter((item) => item === from).length) return from;
// keeps reference to created objects
objectsCache.push(from);
}
// determines whether @from is an instance of any of the following constructors
if (from.constructor === Date || from.constructor === RegExp || from.constructor === Function ||
from.constructor === String || from.constructor === Number || from.constructor === Boolean) {
return new from.constructor(from);
}
if (from.constructor !== Object && from.constructor !== Array) return from;
// creates a new object and recursively iterates over its properties
dest = dest || new from.constructor();
for (prop in from) {
// TODO: allow overwrite existing properties
dest[prop] = (typeof dest[prop] === 'undefined' ?
_clone(from[prop], null, objectsCache) :
dest[prop]);
}
return dest;
}
return (from, dest) => {
const objectsCache = [];
return _clone(from, dest, objectsCache);
};
})();
function Freeman() {
this.name = "Gordon Freeman";
this.character = "Freeman";
this.game = "Half-Life";
this.friends = [];
}
var freeman, david;
freeman = new Freeman();
david = {
name: "David Rivera",
character: "jherax",
friends: [],
languages: new RegExp(/javascript|jquery|c#|sql|java|vb/i),
greeting: function() { return "Hi, I am " + this.name; },
info: {
job: "programmer",
birth: new Date()
}
};
//creamos la referencia circular
freeman.friends = [david, "Barney Calhoun"];
david.friends = [freeman, "John Carmack"];
//clonamos el objeto @david
var cloned = clone(david);
//modificamos propiedades del objeto original
david.name = david.name + " (jherax)";
david.friends.push("Jim Rynor");
//vemos que @clone no fue modificado
console.log("original:", david.name, david.friends);
console.log("clonado:", cloned.name, cloned.friends);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment