Because that’s how variables work: When you say list = bookList, it doesn’t create a copy, it makes list point to exactly the same data as bookList. Or in other words, it makes list an alias (a different name) for bookList.
This is how it works for everything, including numbers and strings, but since they can’t be mutated, you can’t see the aliasing going on. If you want to create a copy of a list, your best bet is to use the spread operator: list = [...bookList]
When you say a = b, you’re assigning a to be an alias of b, that is to say it’s pointing at the same data as b.
When you say a = <some new value>, for example a = 123 you’re saying that a now points to some different data. Since a no longer points to the same data as b, then changes in b won’t be seen in a.
I think a visual explanation is in order, but I lack the graphics skills to execute on it. I’ll give it a try anyway
Starting with list = "foo" and bookList = [1,2,3], you can see how they point to different data (in fact, this kind of variable in other languages is called a pointer but javascript always calls them “variables”)
list----------> "foo"
booklist -----> [1,2,3]
Now, if we assign list = bookList, they point to the same thing:
list ---------+
|
bookList------+--> [1,2,3]
So when you change to either one of these, it’s the same piece of data that changes. Let’s say you said `list[0] = “xyzzy”
list ---------+
|
bookList------+--> ["xyzzy",2,3]
Now let’s reassign list to something else, let’s say list = "bar"
There’s no special difference with arrays and anything else. It’s just that non-object datatypes (arrays are special cases of objects) are immutable, so you can’t tell whether they’re aliased or copies.
In fact, javascript will go out of its way to alias identical strings even when you don’t assign them to each other (it’s called “string interning”). Numbers below some maximum value are typically stored “unboxed” and don’t use a pointer at all. Both are invisible optimizations that only concern people writing JS interpreters.
Internally, they are implemented as pointers (plus some type and gc tagging info). They just aren’t visible from the language the way references are. I knew bringing up the p-word was going to confuse the issue.