2

Ran in to this and I can't find documentation explaining the change- why does .push() change an array when it's applied to a new array that is set equal to that original array?

ex:

var arr = [1, 2, 3, 4, 5]
var newarr = arr
newarr.push(3)
console.log(newarr) //returns [1, 2, 3, 4, 5, 3] as expected
console.log(arr) //returns [1, 2, 3, 4, 5, 3] as well

What's happening here? I'm not applying any methods to arr (that I can see). It looks like arr and newarr are still linked in a way that doesn't apply to other variables, or .push() is invoking the newarr assignment line somehow?

For contrast, this is analogous to what I was expecting-

var x=6
var y=x
y=y*6 
console.log(y)  // now 36
console.log(x)  // still six
skdfsdfa
  • 77
  • 6
  • 1
    arr and newarr is the same object. You need to copy or clone the array: http://stackoverflow.com/questions/3978492/javascript-fastest-way-to-duplicate-an-array-slice-vs-for-loop – mplungjan May 08 '17 at 14:31
  • var newArr = arr.slice(); – Alex May 08 '17 at 14:32
  • 1
    have a look at *copying by refernce vs copying by value* – Jonas Wilms May 08 '17 at 14:32
  • @mplungjan thanks for the link, that's helpful. However, there's no discussion in that link about why this is the case, so I don't think it's an unwarranted question. The comments below about mutable vs immutable and above about copying by reference vs value are helpful- it's not very clear (to a beginner, at least) when a variable is copying a value from another vs when it's a new name pointing at the same thing. – skdfsdfa May 08 '17 at 15:06

2 Answers2

1

The difference between your examples is arrays are mutable, and numbers aren't.

When you write var newarr = arr, you're literally saying that newarr is arr. You need to make a copy of the array to get the behavior you expect.

With the number example, since numbers are immutable, you're never changing the numbers themselves.

Carcigenicate
  • 43,494
  • 9
  • 68
  • 117
  • That's quite helpful, thank you. Immutablity is the one of the keywords I was missing to find more info on this – skdfsdfa May 08 '17 at 15:08
  • @skdfsdfa Immutable means the object itself can't be changed. You can't actually change a number; they're Immutable. A 2 will always be a 2. Arrays on the other hand can be modified, so you need to make copies of them. – Carcigenicate May 08 '17 at 15:09
  • That's pretty obvious with numbers, but not so with strings. After working a bit with strings, I was assuming that assigning a new variable meant making a new thing and giving it the starting value of something else. But turns out strings are immutable too, so it was just copying them in the background (returning a new string), right? Seems a bit odd that the language isn't consistent in how it deals with variables like that. I can't see a use to it, but I'm sure there's a reason for it – skdfsdfa May 08 '17 at 15:16
  • @skdfsdfa Strings are always immutable. That's the case in every language I've ever used. As with all immutability, it allows for optimizations behind the scenes. If you know an object will never change, you can have several objects using the same immutable object without worrying that it will change out from under you. And when you create a variable, the "new thing" you're creating is a reference to an object. – Carcigenicate May 08 '17 at 15:22
  • @skdfsdfa In your array example, you have 2 references pointing to the same array. This is always how it works, it's just with immutable objects the fact that you have multiple references to the same object doesn't matter since the object won't change. I'm not sure if that answered your question. – Carcigenicate May 08 '17 at 15:22
  • It definitely helps, but I've also got some reading to do. Thanks for taking the time to point me in the right direction, I appreciate it – skdfsdfa May 08 '17 at 15:44
  • @skdfsdfa Np. If you really want to dive into immutability, look into a language like Clojure or Haskell where nearly *everything*, including arrays and other objects are immutable. – Carcigenicate May 08 '17 at 15:45
1

To do that you should use the splice method, this method will create a copy of your array, not changing the original.

Nevertheless you should know that when you do the attribution newarr = arr you're not creating a new independent variable that is an array, rather you're created another pointer to the same array.

  • `splice` doesn't create a copy. [It mutates the original.](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice?v=example) – Steve Trout May 08 '17 at 15:52