Copy an object often not a simple task; there are different techniques with their respective pros and cons.
It is especially difficult to offer a complete Javascript solution. Some have performance problems. Others do not work for specific types, such as Date. Endure circular reference is laborious. And almost all of them bump into the problem of prototype (very well explained here).
Clone or copy?
A common confusion is to differentiate the terms clone and copy. In some scenarios the two terms are used interchangeably, referring both to a copy of an object. In others, clone takes a proper meaning, means to copy only the structure of the object (in this case, the prototype).
There is only the caveat; I will not deepen the dicussion and use the most correct term, copy.
Shallow copy vs deep copy
It is important to differentiate the two most common types of copies: Shallow and deep.
A copy Shallow (superficial) makes a copy of the original object, but the properties of the original object still share reference with those of the copy object. Understand how the object "father" is copied but divides your "children".
Already the copy deep (deep) also makes a copy of the properties; the copy of the parent object has its own children (which are also copies).
The following examples are from deep copy, which is what is normally desired.
var copia = JSON.parse(JSON.stringify(original));
The biggest problem of this method is that the functions of the original object would not be present in the copied object.
This is the method that everyone ends up using when the copy doesn’t need to take into account the various other complexities left behind.
Beware of circular references as this method does not support them ("Typeerror: Cyclic Object value").
var copia = eval(original.toSource());
This is one of the worst solutions, as always, Eval is evil, beyond the method toSource not be standard. It’s just as curiosity; do not recommend.
function copiarObj(original) {
var copia = (original instanceof Array) ? [] : {}; // verificando se é um array ou um objeto 'comum' e instanciando a cópia
for (i in original) { // iterando cada propriedade do objeto original
if (original[i] && typeof original[i] == 'object') copia[i] = copiarObj(original[i]); // se for um objeto realiza cópia desse objeto (note a recursividade aqui)
else copia[i] = original[i]; // se não simplesmente copia o valor
}
return copia; // retorna a cópia
};
I shortened it lightly the original method to facilitate teaching.
There are some small problems, such as not working for objects of the type Date, but overall it uses a simple loop for. in and it ends up being very simple. The secret so that it is not a copy Shallow is the recursion made.
Be careful again with circular references, as it is not treated in the loop (generating an infinite loop).
var copia = $.extend(true, {}, original);
I decided to dedicate a part exclusively to jQuery, which, despite being a library and will not be available in all scenarios, is widely used.
The first parameter (true) is for jQuery to make a deep copy; the second ({ }) is the target object, in our case a new object (which is returned by the function).
More complex solutions
As I said, copying an object in Javascript correctly is not an easy task. I have tried to offer only more common and simple examples, since the question does not appear to be for complex cases.
Here are some solutions links that try to be more complete: [1], [2], [3], [4].
Use your framework
If you use a large framework, just like jQuery, it may offer you such a function, such as Underscore.js or the Mootools.
If you are using Node.js there is the module clone (npm, github).
JSON.stringify
throws an exception if the object has circular reference.– BrunoLM
Good remark, I’ll add to the answer.
– talles
Brian Huisman’s method causes an infinite loop in circular reference, test: http://jsfiddle.net/gB55W/
– BrunoLM
Depending on the situation Object.assign can solve the problem, but it copies only enumerable and proper properties of a source object to a destination object. This can make it inappropriate to combine new properties with a prototype if the source objects contain getters. To copy property definitions, including their enumerability, to prototypes Object.getOwnPropertyDescriptor() and Object.defineProperty() should be used instead. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
– Albanir Neves