Метод Object.create() выполняет поверхностное копирование?

Я новичок в JavaScript. Когда я читаю документацию Object.create, она написана так: "Метод Object.create() создает новый объект, используя существующий объект" (ссылка: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create). Ничего не говорится о мелкой копии объекта. Но когда я экспериментировал с приведенным ниже сценарием, я подтвердил, что метод create выполняет поверхностное копирование.

var foo = {
  a : 100,
  details : {
    version : 1.1,
    name : 'Demo of object inheritance'
  },

  printInfo : function(){
    console.log(this.details.version);
    console.log(this.details.name);
    console.log(this.a);
  }

}

var bar = Object.create(foo);

foo.printInfo();
bar.printInfo();

console.log("\n Updating the details and property a of bar object");

bar.details.version = 2.2;
bar.details.name = "Bar object changed the name";
bar.a = 123456;

console.log("\n")
foo.printInfo();
bar.printInfo();

Правильно ли мое понимание? Пожалуйста, укажите мне любую документацию, подтверждающую, что метод create () выполняет поверхностное копирование.

Когда я выполнял в Scratchpad, я видел ниже вывод в консоли.

1.1
Demo of object inheritance
100
1.1
Demo of object inheritance
100

Updating the details and property a of bar object Scratchpad/1:21:1


2.2
Bar object changed the name
100
2.2
Bar object changed the name
123456

3 ответа

Решение

Это не имеет ничего общего с мелкой копией. Вместо этого вы должны понять, как работает Prototype Inheritance в мире Javascript.

Чтобы лучше понять, давайте разберем это на две части:

Чтение свойства из дочернего объекта:

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

Написать свойство в дочернем объекте

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

Давайте возьмем часть вашего кода в качестве примера:


bar.details.version = 2,2;

 What Javascript parser does:
  1. Во-первых, детали будут найдены через поиск по цепочке прототипов и найдены в foo (то есть: bar.details === foo.details)

  2. Во-вторых, версия напрямую устанавливается на объекте details (вот почему this.details.version и this.details.name оба "неожиданно" изменены, как вы видели в результате и в результате bar.details.version === foo.details.version === 2.2))


bar.a = 123456;

What Javascript parser does:

Прежде чем что-либо начинать, bar уже находится, и нет необходимости искать в цепочке прототипов, в результате на панели будет непосредственно установлен a(т. Е. Именно поэтому затрагивается только bar.a с foo.a, все еще удерживающим источник) значение:123456)

Object.Create вообще ничего не копирует, просто устанавливает переданный объект в качестве прототипа нового объекта:

const person = {name: 'Alex', age: 29}
const newPerson = Object.create(person)

console.log(newPerson)

Для того, чтобы сделать мелкую копию, вы можете использовать Object.assign,

const newPersonObj = Object.assign({}, person)
console.log(newPersonObj)

Это создаст совершенно новую копию.

метод create выполняет поверхностное копирование.

- РЕДАКТИРОВАТЬ -

Нет, может показаться, что так, но термин " мелкая копия" был бы неточным. Это было бы больше в соответствии со статьей MDN наследования прототипа здесь

Данный объект oA это имеет name свойство, функция Object.create(oA) создает новый объект oB, Пытаясь получить доступ к собственности oB.name будет искать цепочку прототипов, пока не найдет один на своем прототипе в oA.name,

Пример кода ниже:

/* create one object adam */
const adam = {
 name: 'Adam',
} 
console.log(`does adam have own 'name' property?`, adam.hasOwnProperty('name')) // true

/* create new object bob, whose prototype 'ancestor' is adam */
const bob = Object.create(adam)
console.log(`does bob have own 'name' property? (1)`, bob.hasOwnProperty('name')) // false; the 'name' prop is on adam

/* assigning 'name' on bob doesn't change adam's name, it just 'shadows' it -- accessing 'name' on bob returns the one on bob */
bob.name = 'Bob'
console.log(`does bob have own 'name' property? (2)`, bob.hasOwnProperty('name')) // now true

/* adam and bob now each have their own 'name' property */
console.log(adam.name) // Adam
console.log(bob.name)  // Bob

/* show the relationship of adam and bob */
console.log(`is adam a prototype 'ancestor' of bob?`, adam.isPrototypeOf(bob)) // true, linked via Object.create()
console.log(`is bob a prototype 'ancestor' of adam?`, bob.isPrototypeOf(adam)) // false, the prototype points one way

Надеюсь это поможет. Ура,

Другие вопросы по тегам