4

This question has nothing to do with This question in my opinion, I'm trying to understand some behavior about the javascript core, I don't want a library or something.

I'm trying to understand why this code actually modify const originalArray

const originalArray = [0, 2, 1, 1, 1];

var newArray = originalArray;

var removed = newArray.splice(0,3);

console.log(originalArray);//return [ 1, 1 ]

But at the same time this is not possible:

const originalArray = [];
originalArray = [1];  

So, how can I create a truly immutable Array without a library?

2
  • 1
    Did you try Object.freeze(arr)? Commented May 31, 2018 at 15:45
  • @jonrsharpe is not a duplicate, I've edited the question to avoid the confusion. Commented May 31, 2018 at 18:13

3 Answers 3

9

The reason modifying newArray also modifies originalArray is because variables in JavaScript are just references to objects. When you say newArray = originalArray, you're not copying the array, you're copying the reference. So when you say newArray.splice(0, 3), you're modifying the array referenced by newArray, which originalArray also references.

Similarly, in JavaScript, the word const refers to the reference being constant, not the underlying object. That is to say, you can call mutating methods like .splice on a const variable with no issues. It's when you try to reassign the variable using = or similar that you run into errors.

As others have noted, Object.freeze(_) will make it so you cannot modify the inner object, achieving "immutability" in that you will not be able to modify the underlying object.

For example, if you do the following:

const originalArray = Object.freeze([1, 2, 3]);
let newArray = originalArray; // you can easily use `const` here, but I don't want to confuse the two concepts
newArray.splice(0, 3); // TypeError: Cannot add/remove sealed array elements

If you want a copy of the array that you can modify without modifying the original array, Object.freeze alone will not help you. You will want to "deep copy" the array, which can be done through various methods (easily Google-able, so I will redact them as this answer is getting longer than hoped).

Sign up to request clarification or add additional context in comments.

3 Comments

To clarify, if you replaced the let in the second statement of the example with const, you would achieve the same behavior. If you replaced the let with const and removed Object.freeze, the .splice would be allowed and it would have the same behavior as the code in your original question.
Thank you @River your explanation is very clear. I think the better way instead of Object.freeze is var newArray = originalArray.splice();
That's a good way of deep copying a shallow array. That is, if the elements are just numbers or immutable objects, this will work. However, if you have mutable objects inside the array and modify individual objects, they will still be modified in the original array. To be very certain you're not accidentally creating multiple references to the same object, I recommend using lodash.
4

You could use Object.freeze for that.

const arr = Object.freeze([1, 2, 3]);
console.log(arr);
arr[1] = 7;
console.log(arr);

2 Comments

I don't think this is the correct answer to the body of the question, which is asking why the original array is affected when you modify the new array.
Thank you @Tamas, but I don't understand this behavior of const.
2

const isn't creating a constant variable, like you think, it creates immutable binding. If you write const arr = [] and then arr = {}, you'll get the error. Even Object.freeze freeze only the top level. For example:

const x = Object.freeze([1, 2, 3, [3, 4, 5]]);
x[3].push(20);
console.log(x)

You will get [ 1, 2, 3, [ 3, 4, 5, 20 ] ], if you want it to be completely immutable you have to freeze it recursively, but it hits the performance. You can also create a copy of the array like that and use the new one

const x = [1,2,3,4,5]
const y = x.slice(0, x.length)

1 Comment

Thank you @Vlaev it's definitely a big point against Object.freeze

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.