Если вы пропустили первый из этой серии, то щелкните здесь, это безболезненное 6-минутное чтение, и мы продолжаем совершенствовать наши концепции по мере продвижения.

Итак, мораль истории на этот раз такова.

  • мы все еще находимся в поисках решений для копирования объектов в JavaScript.
  • Но на этот раз нам нужны хорошие однострочные решения.
  • И ничто не сравнится со старой доброй оптимизированной встроенной функцией в JavaScript, и с учетом этого мы рассмотрим братьев JSON и поймем метод Object.assign ().

Обзор братьев JSON (parse & stringify)

let myObj = { 
  a: 1,
  b: { 
       babyObj: 'bulma',
  },
  func: function(){
    console.log("Hi I am an embedded function in an object");
  }
};
let objCopy = JSON.parse(JSON.stringify(myObj));

В прошлый раз мы так высоко отзывались о братьях JSON, но, к сожалению, братья JSON не могут обрабатывать встроенные функции в объект.

Давайте посмотрим, что произойдет, если мы попытаемся вызвать функцию func как для основного объекта myObj, так и для копии objCopy, созданной с использованием функций JSON.

myObj.func();
// "Hi I am an embedded function in an object"
objCopy.func();
//Error: objCopy.func is not a function 

Таким образом, оказывается, что функция JSON stringify игнорирует те свойства в объекте, которые не являются допустимым типом JSON. Поэтому функции игнорируются, поскольку они не поддерживаются в нотации JSON. Отсюда получаем это

console.log(myObj);
//{ a: 1, b: { babyObj: 'bulma' }, func: [Function: func] }
console.log(objCopy);
//{ a: 1, b: { babyObj: 'bulma' } }
//see! we are missing the func in our objCopy

ПРИМЕЧАНИЕ. Мы будем использовать братьев JSON для глубокого копирования объектов только тогда, когда все свойства объекта поддерживаются в JSON (т.е. они являются объектами, массивами, числами, строками, логическими значениями и null)

Object.assign () - функция поверхностного копирования / слияния

Если бы вы могли простить его неспособность выполнить глубокое копирование, вы бы влюбились в метод Object.assign (), потому что он может

  • Помогите скопировать из нескольких объектов в одной функции.
  • перезаписывает аналогичные свойства, что так здорово при слиянии объектов (собственно, это основное использование).

Давайте просто рассмотрим несколько примеров и увидим, насколько оно круто и работает.

1. скопируйте отдельный объект с помощью Object.assign ()

let myObj = { 
  a: 1,
  b: { 
       babyObj: 'bulma',
  }
}
let objCopy = Object.assign({}, myObj);
console.log(myObj);
//{ a: 1, b: { babyObj: 'bulma' } }
console.log(objCopy);
//{ a: 1, b: { babyObj: 'bulma' } }

Милый чувак! это работает, но почему в качестве первого аргумента функции Object.assign () используется «{}»?

Спасибо чувак! Это происходит потому, что первым аргументом функции Object.assign всегда является целевой объект, в котором будут реализованы все окончательные изменения и этот объект будет возвращен, и мы не хотим перезаписывать наш основной объект и следовательно, мы используем пустой объект в качестве конечного пункта назначения, это будет иметь больше смысла в следующих примерах слияния объектов.

Но поскольку копия не является глубокой копией, у нас будет та же проблема, что наш babyObj умирает в обеих копиях, если в какой-либо из них были внесены изменения.

console.log(myObj);
//{ a: 1, b: { babyObj: 'bulma' } }
console.log(objCopy);
//{ a: 1, b: { babyObj: 'bulma' } }  
objCopy.b.babyObj = 'died';
console.log(myObj);
//{ a: 1, b: { babyObj: 'died' } }  
//see! we never touched myObj, hence the shallow copy 
console.log(objCopy);
//{ a: 1, b: { babyObj: 'died' } }

и, к сожалению, нам придется смириться с этой проблемой, если мы хотим использовать метод Object.assign (), но мы можем убедиться, что у нас нет вложенных объектов или массивов (ой, да, массивы тоже), чтобы избежать побочных эффектов.

let myObj = {
  a: [1,2,3,4]
}
let objCopy = Object.assign({}, myObj);
objCopy.a[0] = 10;
console.log(myObj);   
//{ a: [ 10, 2, 3, 4 ] }   So arrays as well Hmm! Oh man 
console.log(objCopy); 
//{ a: [ 10, 2, 3, 4 ] }

2. Слияние объектов с помощью Object.assign ()

До сих пор это было разочарованием, но давайте подбодримся на этот раз и посмотрим на приятную сторону этой функции.

var obj1 = { a: 1 };
var obj2 = { b: 2 };
var obj3 = { c: 3 };
var obj = Object.assign(obj1, obj2, obj3);
console.log(obj); 
// { a: 1, b: 2, c: 3 } 
//Yay! we have merged many objects into one
console.log(obj1);
// { a: 1, b: 2, c: 3 }, target object itself is changed.

Итак, мы объединили объекты, но, как мы знаем, первый аргумент всегда является целевым объектом (здесь реализованы основные изменения) в Object.assign (), а остальные аргументы действуют как источники, следовательно, мы получили этот объект «obj1», измененный и поэтому мы всегда используем пустой объект «{}» в качестве первого аргумента.

Давайте рассмотрим еще один модифицированный пример, чтобы понять, как происходит перезапись свойств объекта в Object.assign (), когда они имеют одинаковые свойства.

var obj1 = { a: 1, b: 1, c: 1 };
var obj2 = { b: 2, c: 2 };
var obj3 = { c: 3 };
var obj = Object.assign({}, obj1, obj2, obj3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(obj1); // { a: 1, b: 1, c: 1 }
console.log(obj2); // { b: 2, c: 2 }
console.log(obj3); // { c: 3 }

Это довольно изящный пример, демонстрирующий, что следующий аргумент всегда имеет более высокий приоритет, когда дело доходит до перезаписи одних и тех же свойств, и поскольку мы использовали пустой объект «{}» в качестве первого аргумента (цели), мы не изменяем ни один из наши основные цели.

Это хороший инструмент для объединения объектов, и он пригодится в тех случаях, когда нам нужно передать объекты в качестве аргументов функции, подробно обсуждаемой здесь, при простом чтении за 3 минуты.

Я настоятельно рекомендую поиграть с этой функцией, чтобы лучше понять, но мы немного отклонились от нашей цели копирования объектов, но это было актуальное обсуждение.

В следующей статье мы снова найдем больше проблем с копированием объектов, найдем решения и с точки зрения оптимизации и продолжим уточнять наши концепции, копая глубже, надеюсь, в конце этой серии мы придумаем нашу собственную библиотеку для решения этой проблемы. однажды и на всегда.