4

I am newbee to JavaScript. When I read the Object.create documentation, it is written like 'The Object.create() method creates a new object, using an existing object' (Ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create). It do not mention anything about the shallow copy of the object. But when I experimented with below script, I confirmed that, create method is performing shallow copy.

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();

Is my understanding correct? Please point to me any documentation that confirms create() method performs shallow copy.

When I executed in Scratchpad, I seen below output in console.

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
Hari Krishna
  • 3,658
  • 1
  • 36
  • 57
  • 3
    It doesn't copy the passed object at all, instead it sets the *internal prototype* of the newly created object to the passed object. – CertainPerformance Oct 23 '18 at 05:29
  • nope, its just create the same object. if you want to clone it u can use new es6 {...object} – Talg123 Oct 23 '18 at 05:30
  • 2
    You forgot to quote the most important part *"[...] using an existing object **to provide the newly created object's `__proto__`** ."* Granted, it's not the best description, but it's a community owned wiki after all. *edit:* I updated the description. – Felix Kling Oct 23 '18 at 05:31
  • But in my example, details is not a prototype property, it is the foo object property itself. But when I changed the bar.details, it is reflecting in foo.details also...any reason for this. – Hari Krishna Oct 23 '18 at 05:34
  • 1
    Objects are reference-type and mutable values. When you create an object, you really get a reference to a memory location. Mutating an object has the effect that any reference "reflects" the new state of the object. Simplest example: `var foo = {}; var bar = foo; foo.baz = 21; console.log(bar);`. A prototype is just another object. In your example, `bar` has an *internal* reference to `foo`. If you don't quite understand prototypes yet, I recommend https://github.com/getify/You-Dont-Know-JS/blob/0cc17c53ff772e20dfd6a7072c965df2486116e8/this%20%26%20object%20prototypes/ch5.md – Felix Kling Oct 23 '18 at 07:15

3 Answers3

3

Object.Create does not copy anything at all, it just sets the passed object as the prototype of a new object:

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

console.log(newPerson)

enter image description here

In order to make a shallow copy, you can use Object.assign.

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

This will create entirely new copy. enter image description here

Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
Sandip Nirmal
  • 2,283
  • 21
  • 24
  • Hi Sandip, Are you tried with nested object. I observed, it is performing shallow copy.... – Hari Krishna Oct 23 '18 at 05:54
  • 2
    @HariKrishna: As has been said a couple of times, and as has been shown in this answer, `Object.create` does *not* create a copy at all. – Felix Kling Oct 23 '18 at 07:16
  • It took me a while to grasp that. IMHO, as the answer below says, the key to understanding it is to 'figure out how Prototype inheritance works'. – Ya. May 13 '22 at 14:34
1

It has nothing to with shallow copy. Instead, you have figure it out how Prototype Inheritance works in Javascript world.

To have a better understanding, let's break this down into following 2 parts:

Reading property from child object:

When you try to access a property from a child object, Javascript parser will try to search through up prototype chain until it manages to find it else return undefined if not found.

Write property in child object

It will first try to locate that the object to which the your targeted property belongs, and then directly set that property on that object.

Let's take part of your code as example:


bar.details.version = 2.2;

 What Javascript parser does:
  1. First, details will be located through prototype chain searching and it will be found on foo (ie: bar.details === foo.details)

  2. Second, version is directly set on details object(that's why this.details.version and this.details.name are both "unexpectedly" changed as you saw in your result and as a result bar.details.version === foo.details.version === 2.2))


bar.a = 123456;

What Javascript parser does:

Before anything gets started, bar is already located and there's no need to search though prototype chain, as a result, a will be directly set on the bar (ie. that's why only bar.a is affected with foo.a still holding the origin value:123456)

Deng Zhebin
  • 1,222
  • 1
  • 9
  • 17
-1

create method is performing shallow copy.

-- EDIT --

Nope, it may seem that way but the term shallow copy would be inaccurate. It would be more in line with prototypal inheritance MDN article here

Given an object oA that has a name property, function Object.create(oA) creates a new object oB. Trying to access property oB.name would look up the prototype chain until it finds one on its prototype at oA.name.

Sample code below:

/* 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

Hope this helps. Cheers,

jonathangersam
  • 1,137
  • 7
  • 14
  • Its not a "clone" and your "rule of thumb" certainly makes no sense at all. – Jonas Wilms Oct 23 '18 at 05:51
  • @JonasWilms I must disagree, the word 'clone' is a sufficient metaphor in this case. As per [MDN Object.create()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create): "The Object.create() method creates a new object...". – jonathangersam Oct 23 '18 at 06:12
  • 1
    Your answer is misleading. Your "own" and "shared" properties comparison is incorrect. Here would be a more fair example: `ob.hobbies = ['dining']`. This will also modify "the clone's property", and not the original, even though the value is a reference type. As for *"the clone will have its own properties that are value type (ie string, int, bool)"* Nope: `Object.create({baz: 21}).hasOwnProperty('baz'); // false`. The value of the properties is almost irrelevant for explaining how prototypes work. More interesting is the result of `obj.hasOwnProperty(...)`. – Felix Kling Oct 23 '18 at 07:19
  • @FelixKling I see your point. Yup you're right the accurate answer should have led to prototype chains. I have edited my answer to reflect this, thanks. – jonathangersam Oct 23 '18 at 08:37