0

I have declared the following object:

const restaurant = {
  openingHours: {
    thu: {
      open: 12,
      close: 22,
    },
    fri: {
      open: 11,
      close: 23,
    },
    saturday: {
      open: 0, // Open 24 hours
      close: 24,
    },
  }
};

than i desturctured openingHours object into a new variable name friday:

const { fri: friday } = restaurant.openingHours;

than i modified the value of open hour property in friday object:

friday.open = 5;

and in the end i checked if the change affect original restaurant property:

console.log(restaurant.openingHours.fri.open, friday.open); // prints 5 5

I can't understand why it change the value of restaurant.openingHours.fri.open to 5?

Cause if i had the following code:

let originalAge =5;
let newAge = originalAge;
newAge =6;
console.log(originalAge) // will print 5, So what is the difference here?

enter image description here

Eitanos30
  • 1,331
  • 11
  • 19
  • 1
    objects are copied by reference. primitives are copied by value – andrewgi Dec 27 '20 at 13:18
  • `friday` is a reference to an object, which is the object that the `fri` property points to in memory. See [Modifying a copy of a JavaScript object is causing the original object to change](https://stackoverflow.com/q/29050004) – Nick Parsons Dec 27 '20 at 13:18
  • @Nick Parsons, isn't ***friday*** is a reference to primitive type (string)? exactly as in my example ***originalAge*** is a reference to primitive type (number)? – Eitanos30 Dec 27 '20 at 13:21
  • 1
    @Eitanos30 it is a reference to the object `{open: 11, close: 23,}`, not a string (why do you think it is a string?) – Nick Parsons Dec 27 '20 at 13:22
  • @NickParsons, you are right. my fault. I have confused with open – Eitanos30 Dec 27 '20 at 13:40
  • @Eitanos30 no worries, I tried to clarify my comment in an answer below, seems like you understand it now though – Nick Parsons Dec 27 '20 at 13:47
  • @NickParsons, maybe you can help me please. I saw a lecture in JS, that says that also primitive type are referenced by a reference (in contrast to java). So if a primitive type is referenced by a reference (exactly like a non primitive type), so why when writing an assignment between two primitive types the assignment takes the value of the right operand and not it's address? I have add a screen shot from the video to my post – Eitanos30 Dec 27 '20 at 14:04
  • 2
    JavaScript primitives are immutable so you can't tell whether they are copied by value or reference. Formally, they are references but most implementations copy numbers by value for efficiency. And since they are immutable and have custom comparisons, you cannot detect the difference. – Raymond Chen Dec 27 '20 at 14:26
  • @RaymondChen, not easy :) thanks – Eitanos30 Dec 27 '20 at 15:34

3 Answers3

1

Because "friday" is an object and passed as reference whereas originalAge is a primitive value (number/string/boolean ...).

You can try this :

const { fri } = restaurant.openingHours;
const friday = { ...fri };

This will make a shallow copy of friday (if will create a real copy if all of the first level values if they are all primitives)

bossno
  • 587
  • 6
  • 12
1

You have pulled out reference to the inner object fir via destructuring operator. It still refers to the inner object of openingHours

To unbind it you can use following snippet:


const friday = Object.assign({}, restaurant.openingHours.fri);

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign - read more about assign method.

Monsieur Merso
  • 1,459
  • 1
  • 15
  • 18
  • 1
    You are trying to destructure ```fri``` when on the right side of the statement you already pointing to the fri: ```restaurant.openeningHours.fri```. So it tries to lookup ```fri``` property inside ```restaurant.openingHours.fri```. In ordrer this to work: ```const { fri: { open: openess }, } = restaurant.openingHours;``` – Monsieur Merso Dec 27 '20 at 13:34
1

The following destructuing syntax:

const { fri: friday } = restaurant.openingHours;

... desugars to:

const friday = restaurant.openingHours.fri;

Both of the above set the variable friday to a reference to the object:

{
  open: 11,
  close: 23,
}

Since the above object is also the same reference in your restaurant.openingHours.fri object, both friday and restaurant.openingHours.fri will be referencing the same object in memory. As a result, when you do:

friday.open = 5;

you're changing the one object in memory, which both friday and restaurant.openingHours.fri are pointing to.

In your example, however, you're working with primitives (ie: 5), which are copied by value. And so they are not shared in your memory (so changing one does not change the other).

One way you can make a copy of the .fri object by updating your destructuring syntax to use the rest syntax:

const { fri: {...friday} } = restaurant.openingHours;

const restaurant = {
  openingHours: {
    thu: {
      open: 12,
      close: 22,
    },
    fri: {
      open: 11,
      close: 23,
    },
    saturday: {
      open: 0, // Open 24 hours
      close: 24,
    },
  }
};

const { fri: {...friday} } = restaurant.openingHours;
friday.open = 5;
console.log(friday, restaurant.openingHours.fri);
Nick Parsons
  • 45,728
  • 6
  • 46
  • 64
  • i think you used here a spread and not rest. Am i wrong? – Eitanos30 Dec 27 '20 at 14:39
  • @Eitanos30 I mean rest: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Rest_syntax_parameters – Nick Parsons Dec 28 '20 at 00:37
  • what are the order of the operation in *const { fri: {...friday} } = restaurant.openingHours;* assignment? First *restaurant.openingHours;* is destruct to friday and only than the rest operation occurs? on answer above your answer it looks like a spread, in your answer it is a rest? – Eitanos30 Dec 28 '20 at 09:59
  • 1
    First the right-hand side (RHS) of the `=` is evaluated, which evaluates an object, then the LHS of the `=` is evaluated. The `{...friday}` is being used within the destructuring assignment syntax to extract the remaining properties from the `fri` object (in this case the remaining properties are all the properties in the `fri` object), so it is classified as "rest" (although MDN seems to use rest/spread syntax interchangeably). In the example above, `...` is being used within an object literal, so in that case it is the spread syntax as they're "expanding" the `fri` object into the new object – Nick Parsons Dec 28 '20 at 11:14