I noticed that if there is any object, and if you create a new one, assigning the value of this object to it, and change some field in it, then it will also change in the old one:

var a = {prop: 1}; document.getElementById("1").textContent = a.prop + ''; var b = a; b.prop = 2; document.getElementById("2").textContent = a.prop + ''; 
 <p id='1'></p> <p id='2'></p> 

What are some ways to create a copy of an object? That is, the changes to the new variable do not affect the old one.

  • 2
  • 2
    and judging by ES6 in general, you can: var obj = { a: 1 }; var copy = Object.assign({}, obj); console.log(copy); // { a: 1 } var obj = { a: 1 }; var copy = Object.assign({}, obj); console.log(copy); // { a: 1 } var obj = { a: 1 }; var copy = Object.assign({}, obj); console.log(copy); // { a: 1 } developer.mozilla.org/ru/docs/Web/JavaScript/Reference/… - Aleksey Shimansky
  • @ Alexey Shimansky, it’s worth making a canonical answer :) - Grundy
  • @ Alexey Shimansky, assign, does not do deep copying - Grundy
  • @Grundy here and write the answer, mentioning this ;-) - Alexey Shimansky

1 answer 1

The whole point is that in Javascript all objects are assigned by reference without exceptions, this means that no matter how many variables you assign an object, it will always remain in memory in the singular.

 var a = {prop: 1} var b = a; var c = b; (c===b&&b===a&&c===a) // true 

As long as at least one variable refers to an object, it continues to exist. When the last variable referring to an object is deleted, the object itself is also deleted.

 var a = {prop: 1}; var b = a; a.prop = 2; delete a; (b.prop===2); // true 

In javascript, there is no operator that allows you to make a copy of an object, so copying objects in Javascript comes down to creating a new one with exactly the same properties as the first one.

 var a = {prop: 1}; var b = {}; b.prop = a.prop; 

However, it is necessary to take into account the fact that the property of an object may contain another object, which will also be passed by reference, in the case of assignment, so the following example will create a wrong clone:

 var a = { prop: { sub: 1 } } var b = {}; b.prop = a.prop; 

Because the sub property will be the same for both objects.

 a.prop.sub = 2; (b.prop.sub===1) // False 

Therefore, when creating a copy of an object, it is necessary to check whether its properties are not objects, and in this case, perform the same operation with them as we turned with a and b.

In general, the function of creating a clone of an object will look like this:

 function makeClone(obj) { let clone = {}; // Создаем новый пустой объект for (let prop in obj) { // Перебираем все свойства копируемого объекта if (obj.hasOwnProperty(prop)) { // Только собственные свойства if ("object"===typeof obj[prop]) // Если свойство так же объект clone[prop] = makeClone(obj[prop]); // Делаем клон свойства else clone[prop] = obj[prop]; // Или же просто копируем значение } } return clone; } 

However, this function is not universal and will not work correctly in all cases, since in Javascript, in addition to simple objects, there are also built-in objects and objects created from prototypes that can no longer just be taken and copied. These are instances of Image, Date, HTMLElement, custom classes, etc. In addition, there are cases when nested properties contain references to objects that indirectly return us to ourselves. For example:

 var a = {}, b = {prop: a}; a.prop = b; 

If you run the makeClone function for variable a, then the clone creation process will continue indefinitely, which will cause "Maximum call stack size exceeded". So there are so many nuances of cloning an object, so it’s better not to reinvent the wheel, but to use ready-made solutions such as jQuery.extend:

 var a = {prop: 1}; var clone = jQuery.extend(true, {}, a); 

In addition, stand-alone analogues of this function can be found on npmjs.

PS: About Object.assign - this is an experimental method and so far it is not supported by browsers, and it seems that babel without special plug-ins also does not perceive it.

  • And what except objects is always assigned by reference? - Yuri
  • one
    Objects only. Arrays are also objects if che. - Vladimir Morulus 4:39 pm
  • one
    Object.assign - only in IE is not supported, the rest of the latest browser versions have already implemented it - Grundy
  • Well, ready-made solutions, including jQuery.extend, also do not cover all possible options - Grundy