2

I just noticed something weird with cloning and pushing items. Here's example:

let a = { foo: [1,2] };
let b = Object.assign({}, a) // cloning object and getting new reference
a === b // gives false which is what I want

now I do push on object a:

a.foo.push(3)

now a.foo is [1,2,3] but b.foo is also [1,2,3]

but if I do

a.foo = a.foo.concat(4)

a.foo is [1,2,3,4] and b.foo is [1,2,3]

Question is: Why is that?

SzymonPoltorak
  • 616
  • 1
  • 6
  • 12
  • the reason `a.foo` is `[1,2,3,4]` and `b.foo` is `[1,2,3]` is that `concat()` returns a whole new array which will replace `a.foo` – miqe Jun 20 '17 at 08:06

5 Answers5

3

a.foo and b.foo are pointing to the same reference,but .concat() returns a new array so they now are pointing 2 different array reference

2

Object.assign does something that is called shallow cloning or shallow copying. If the source value is a reference to an Object, it only copies that reference value.

Check the docs here and read Warning for Deep Clone.

That is also why a push affects both Objects a and b, because it is in fact the same array on which the operation takes place.

The Array.prototype.concat method returns a new Array Object, which you assign to a.foo (a.foo = a.foo.concat(4)), so both foo references will now point to 2 different array objects.

The concat() method is used to merge two or more arrays. This method does not change the existing arrays, but instead returns a new array.

                               Object references

Nico Van Belle
  • 4,911
  • 4
  • 32
  • 49
1

Why is that?

Object.assign({}, a) does shallow copy of your object a

const foo = {bar: []}

const baz = Object.assign({}, foo)

console.log(foo.bar === baz.bar)

But Array.prototype.concat creates new array

const foo = []
const bar = foo.concat()

console.log(foo === bar)
Yury Tarabanko
  • 44,270
  • 9
  • 84
  • 98
  • why are you doing foo.bar === baz.bar, explain why foo === baz is false if it is a shalow copy – AurA Jun 20 '17 at 08:08
  • @AurA Why would it be true? – Yury Tarabanko Jun 20 '17 at 08:09
  • that would be false because it is an object and object structure gets copied in shallow copy but variables point to the same, that is the reason it is returning false here... It is an empty object but still structure gets copied... – AurA Jun 20 '17 at 08:14
  • @AurA Doesn't it obvious? Well, atlaest for OP who used this method to do "cloning object and getting new reference". Copy is still a copy though it is shallow. – Yury Tarabanko Jun 20 '17 at 08:17
1

Because in your case a.foo and b.foo reference the same array. so a change in one side will affect the other one, and Array.prototype.concat returns a new array and doesn't alter the first array that's why you got differents results in the second call, as opposed to array.prototype.push which will alter the initial array.

Array.prototype.concat:

The concat() method is used to merge two or more arrays. This method does not change the existing arrays, but instead returns a new array.

array.prototype.push:

The push() method adds one or more elements to the end of an array and returns the new length of the array.

You may also need to read What is the most efficient way to deep clone an object in JavaScript?, because Object.assign() will just copy the reference to the exisiting objects.

cнŝdk
  • 31,391
  • 7
  • 56
  • 78
0

read here

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

assign dont do a deep copy, so a.foo and b.foo point to same array so when you push it gets added to same array

but when you do concat it actually returns new array and now both arrays are different

ashish singh
  • 6,526
  • 2
  • 15
  • 35