... Я ожидаю, что a принимает значение b, а не ссылку ...
Это неверно.Переменные содержат значения.В случае объекта значение представляет собой «ссылку на объект», которая сообщает движку JavaScript, где находится объект (в другом месте) в памяти.Таким образом, a = b
a
"указывает" на тот же объект, b
"указывает" на.Если вы измените свойства этого объекта, вы будете наблюдать эти изменения независимо от переменной, из которой вы получаете ссылку.
После первоначальной настройки в памяти у вас будет что-то подобное (различные детали опущены):
+−−−−−−−−−−−−−−+
a: Ref5465−−−−>| (object) |
+−−−−−−−−−−−−−−+ +−−−−−−−−−−+
| foo: Ref8761 |−−−−>| (object) |
+−−−−−−−−−−−−−−+ +−−−−−−−−−−+
| bar: 1 |
+−−−−−−−−−−+
+−−−−−−−−−−−−−−+
b: Ref1574−−−−>| (object) |
+−−−−−−−−−−−−−−+ +−−−−−−−−−−+
| foo: Ref4456 |−−−−>| (object) |
+−−−−−−−−−−−−−−+ +−−−−−−−−−−+
| bar: 2 |
+−−−−−−−−−−+
(Эти значения «ref», конечно, являются концептуальными; мы никогда не видим их на самом деле.)
затем, когда вы делаете a = b
, объект, который a
используемый для ссылки подходит для сбора мусора, и вместо этого у вас есть это:
a: Ref1574−−+
|
|
| +−−−−−−−−−−−−−−+
+−>| (object) |
| +−−−−−−−−−−−−−−+ +−−−−−−−−−−+
| | foo: Ref4456 |−−−−>| (object) |
| +−−−−−−−−−−−−−−+ +−−−−−−−−−−+
b: Ref1574−−+ | bar: 2 |
+−−−−−−−−−−+
Обратите внимание, что a
теперь имеет то же значение "ref", что и b
.Естественно, a.foo.bar = 3
изменяет это свойство bar
, на которое указывают a
и b
(косвенно).
Если вы хотите сделать копию объекта,Вы можете сделать поверхностную копию с помощью a = Object.assign({}, b)
или (в ES2018 +) a = {...b}
.Но если вы хотите скопировать объект, на который ссылается foo
, вам потребуется копия deep ;см. ответы на этот вопрос .