JavaScript частично является объектно-ориентированным языком.

Чтобы изучить JavaScript, нам нужно изучить объектно-ориентированные части JavaScript.

В этой статье мы рассмотрим копирование объектов.

Глубокая копия

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

Например, мы можем написать:

function deepCopy(source, target = {}) {
  for (const key in source) {
    if (source.hasOwnProperty(key)) {
      if (typeof source[key] === 'object') {
        target[key] = Array.isArray(source[key]) ? [] : {};
        deepCopy(source[key], target[key]);
      } else {
        target[key] = source[key];
      }
    }
  }
  return target;
}

Мы перебираем каждую клавишу source.

Затем мы проверяем каждое свойство, если это собственное свойство.

Затем мы проверяем, является ли объект source[key] объектом.

Если source[key] - это массив, мы создаем массив, а затем выполняем копирование.

Если это объект, мы рекурсивно вызываем deepCopy, чтобы сделать копию.

В противном случае мы присваиваем значение из source target.

После этого мы возвращаем target.

Затем мы можем использовать его, написав:

const foo = {
  a: 1,
  b: {
    c: 2
  }
}
const bar = deepCopy(foo, {});
console.log(bar);

deepCopy рекурсивно скопирует все собственные свойства из foo в bar.

So bar is:

{
  "a": 1,
  "b": {
    "c": 2
  }
}

Array.isArray позволяет нам проверять, является ли что-то массивом, независимо от контекста.

Использование метода object ()

Мы можем создать object функцию для создания функции, возвращающей экземпляр конструктора.

Это предложение от Дугласа Крокфорда, и оно упрощает настройку прототипа, поскольку принимает объект прототипа.

Например, мы можем написать:

function object(proto) {
  function F() {}
  F.prototype = proto;
  return new F();
}

Мы создаем функцию object со свойством proto.

Затем мы установили это как F ‘s prototype.

И мы возвращаем экземпляр F.

Это отличается от Object.create, поскольку у нас есть экземпляр конструктора.

Затем мы можем использовать его, написав:

const obj = object({
  foo: 1
});

Тогда obj унаследует объект, который мы передали.

Сочетайте свойства прототипного наследования и копирования

Мы можем смешивать прототипное наследование с копированием свойств.

Для этого мы можем расширить функцию object, написав:

function object(proto, moreProps) {
  function F() {}
  F.prototype = proto;
  const f = new F();
  return {
    f,
    ...moreProps
  };
}
const obj = object({
  foo: 1
}, {
  bar: 2
});

Мы добавляем параметр moreProps к функции object, что позволяет нам добавлять дополнительные свойства, передавая ей второй аргумент.

moreProps распространяется на объект, который мы возвращаем, так что мы возвращаем новый объект.

Следовательно, obj это {f: F, bar: 2}, поскольку мы наследуем от F.prototype и moreProps.

Заключение

Мы можем смешивать прототипное наследование с копированием свойств, чтобы получить все свойства, которые нам нужны в объекте.

Глубокое копирование может быть выполнено путем рекурсивного копирования свойств из исходного объекта в целевой.