Ресурсы: Статья про клонирование Object.assign() Spread оператор
Ожидаемое поведение:
Код
let a = 5,
b = a;
b = b + 5;
console.log(b); // 10
console.log(a); // 5
Теперь рассмотрим на примере с объектами, создадим какой-нибудь объект
obj и переменную
copy, в которую положим значение объекта
obj Код
const obj = {
a: 5,
b: 1
}
const copy = obj;
Изменяем значение свойства
a в объекте
copy и выведем в консоль содержимое обоих объектов:
Код
const obj = {
a: 5,
b: 1
}
const copy = obj; // здесь передаётся ссылка на объект obj
copy.a = 10;
console.log(obj); // { a: 10, b: 1 }
console.log(copy); // { a: 10, b: 1 }
Как видно, значение свойства
a поменялось также и в объекте
obj. Происходит это потому, что в данном случае идёт передача по ссылке, то есть в переменной
copy мы сохранили не копию значения объекта
obj, а ссылку на этот объект, именно поэтому, внося изменения в объект
copy, мы вносим также изменения в объект
obj Как же создаются копии объектов, массивов и прочего?
Использование цикла для создания копии
Напишем функцию, которая будет как аргумент принимать наш объект и создавать новый
objCopy, перебирая свойства первоначального объекта
Код
function copy(mainObj) {
let objCopy = {};
let key; // вариант объявления переменной вне цикла
for (key in mainObj) {
objCopy[key] = mainObj[key];
}
return objCopy;
}
Теперь добавим какой-нибудь объект, который будем передавать в нашу функцию в качестве аргумента
Код
const numbers = {
a: 2,
b: 5,
c: {
x: 7,
y: 4
}
};
Теперь создадим переменную и в неё сохраним наш новый объект, копию объекта, переданного в функцию
Код
const newNumbers = copy(numbers);
Пробуем теперь изменить значение какого-то свойства в новом объекте, копии первоначального, и затем выведем оба объекта в консоль
Код
function copy(mainObj) {
let objCopy = {};
let key; // вариант объявления переменной вне цикла
for (key in mainObj) {
objCopy[key] = mainObj[key];
}
return objCopy;
}
const numbers = {
a: 2,
b: 5,
c: {
x: 7,
y: 4
}
};
const newNumbers = copy(numbers);
newNumbers.a = 10;
console.log(numbers);
console.log(newNumbers);
Цитата
{ a: 2, b: 5, c: { x: 7, y: 4 } } // значение a не изменилось
{ a: 10, b: 5, c: { x: 7, y: 4 } } // значение a изменилось
Но,если поменять значение свойства
c в копии объекта
То оно поменяется и в первоначальном объекте
Цитата
{ a: 2, b: 5, c: { x: 10, y: 4 } }
{ a: 2, b: 5, c: { x: 10, y: 4 } }
Всё дело в том, что есть
глубокие и
поверхностные копии объектов, и в данном случае мы сделали поверхностную копию объекта.
В ней на первом уровне вложенности копия отрабатывает нормально, но на втором уровне вложенности в объекте опять работает ссылочный тип данных.
Создание копии объекта с помощью метода Object.assign()
Метод Object.assign() используется для копирования значений всех собственных перечисляемых свойств из одного или более исходных объектов в целевой объект. После копирования он возвращает целевой объект.
Синтаксис метода:
Код
Object.assign(target, ...sources)
target - это объект, в который мы хотим поместить значения свойств нужных объектов
sources - необходимые объекты
Код
const numbers = {
a: 2,
b: 5,
c: {
x: 7,
y: 4
}
};
const add = {
d: 17,
e: 20
};
console.log(Object.assign(numbers, add));
Цитата
{ a: 2, b: 5, c: { x: 7, y: 4 }, d: 17, e: 20 }
И в данном случае мы опять получили независимую поверхностную копию объекта. Тоже самое можно проделать и с пустым объектом, чтобы просто создать копию нужного объекта.
Код
const add = {
d: 17,
e: 20
};
const clone = Object.assign({}, add);
clone.d = 20;
console.log(add);
console.log(clone);
Цитата
{ d: 17, e: 20 } { d: 20, e: 20 }
Создание копии массива
Если написать так, то в
newArray мы получим ссылку на первоначальный массив, а не копию
Код
const oldArray = ['a', 'b', 'c'];
const newArray = oldArray;
Вместо этого воспользуемся методом
slice(), чтобы получить поверхностную копию массива
Код
const newArray = oldArray.slice();
console.log(newArray); // ['a', 'b', 'c']
Метод slice() возвращает новый массив, содержащий копию части исходного массива.
Синтаксис метода:
Код
arr.slice([begin[, end]])
begin - необязательный параметр
Индекс (счёт начинается с нуля), по которому начинать извлечение.
Если индекс отрицательный,
begin указывает смещение от конца последовательности. Вызов
slice(-2) извлечёт два последних элемента последовательности.
Если
begin не определён,
slice() начинает работать с индекса 0.
Если
begin больше длины последовательности, вернётся пустой массив.
end - необязательный параметр
Индекс (счёт начинается с нуля), по которому заканчивать извлечение. Метод
slice() извлекает элементы с индексом меньше
end.
Вызов
slice(1, 4) извлечёт элементы со второго по четвёртый (элементы по индексам 1, 2 и 3).
Если индекс отрицательный,
end указывает смещение от конца последовательности. Вызов
slice(2, -1) извлечёт из последовательности элементы начиная с третьего элемента с начала и заканчивая вторым с конца.
Если
end опущен,
slice() извлекает все элементы до конца последовательности (
arr.length).
Код
const animals = ['ant', 'bison', 'camel', 'duck', 'elephant'];
console.log(animals.slice(2));
// Expected output: Array ["camel", "duck", "elephant"]
console.log(animals.slice(2, 4));
// Expected output: Array ["camel", "duck"]
console.log(animals.slice(1, 5));
// Expected output: Array ["bison", "camel", "duck", "elephant"]
console.log(animals.slice(-2));
// Expected output: Array ["duck", "elephant"]
console.log(animals.slice(2, -1));
// Expected output: Array ["camel", "duck"]
console.log(animals.slice());
// Expected output: Array ["ant", "bison", "camel", "duck", "elephant"]
Spread оператор
Код
const video = ['youtube', 'vimeo', 'rutube'];
const blogs = ['wordpress', 'livejournal', 'blogger'];
const internet = [];
Задача перенести данные из первых двух массивов в третий.
Используем для этого
spread оператор (
...), который разворачивает структуру массивов на отдельные значения.
Код
const video = ['youtube', 'vimeo', 'rutube'];
const blogs = ['wordpress', 'livejournal', 'blogger'];
const internet = [...video, ...blogs, 'vk', 'facebook'];
console.log(internet);
Цитата
[
'youtube',
'vimeo',
'rutube',
'wordpress',
'livejournal',
'blogger',
'vk',
'facebook'
]
Пример посложнее:
Код
function log(a, b, c) {
console.log(a);
console.log(b);
console.log(c);
}
const num = [2, 5, 7];
log(...num);
Так как при вызове функции
spread оператор развернет массив на отдельные составляющие, то они попадут как аргументы в переменные
a, b, c Похожим образом мы можем создать поверхностную копию массива или объекта
Код
const arr = ['a', 'b', 'c'];
const newArr = [...arr];
const obj = {
one: 1,
two: 2
};
const newObj = { ...obj };
Добавлять комментарии могут только зарегистрированные пользователи.