Если вы пропустили первый из этой серии, то щелкните здесь, это безболезненное 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 минуты.
Я настоятельно рекомендую поиграть с этой функцией, чтобы лучше понять, но мы немного отклонились от нашей цели копирования объектов, но это было актуальное обсуждение.
В следующей статье мы снова найдем больше проблем с копированием объектов, найдем решения и с точки зрения оптимизации и продолжим уточнять наши концепции, копая глубже, надеюсь, в конце этой серии мы придумаем нашу собственную библиотеку для решения этой проблемы. однажды и на всегда.