Путаница в Javascript по переменным, определяемым ссылкой на значение - PullRequest
5 голосов
/ 28 февраля 2012

Я понимаю следующее свойство языка javascript:

var bar = 1;
var foo = bar;
bar = "something entirely different";
// foo is still 1

Однако при попытке применить эту логику к объекту она действует по-другому:

var bar = {};
bar.prop = 1;
var foo = bar;
bar.prop = "something entirely different";
// foo.prop now changes to "something entirely different"
// but...
bar = "no longer an object";
// now foo remains an object with the prop property

Может кто-тоскажите что происходит и почему есть разница?

Ответы [ 3 ]

1 голос
/ 28 февраля 2012

Давайте рассмотрим это построчно:

var foo = bar;

Все, что делают имена объектов - это удерживает адреса в памяти.Таким образом, в этом утверждении вы заставляете foo хранить тот же адрес памяти, что и bar.Например, если bar содержало 0xFF, то с помощью присваивания, которое вы сделаете, foo также будет содержать 0xFF.

Однако имейте в виду, что bar и foo - два разных объекта, они случаютсяпросто хранить один и тот же адрес в памяти.

Теперь, поскольку они действительно содержат один и тот же адрес в памяти, мутирующие члены bar также будут влиять на элементы foo, поскольку они связаны стот же объект.

bar.prop = "something entirely different";  // affects foo.prop also

Однако вот ключевой момент, о котором следует помнить:

Assignment only changes what the name of the object is bound to, and does not affect any other objects.

Другими словами, приведенное ниже утверждение bar содержит другой адрес памяти, но это не влияет на foo.

bar = "no longer an object"; // Made bar hold a different memory address

Теперь, объясняя цитату:

Javascript is always pass by value, but when a variable refers to an object (including arrays), the "value" is a reference to the object.

Возьмем этот пример:

function f(obj1, obj2)
{
    obj1.prop = 10;
    obj2 = {prop: 20};
}

var bar = {prop: 1};
var foo = {prop: 2};
f(bar, foo);
console.log("bar.prop: " + bar.prop + ", foo.prop: " + foo.prop);

Это выводит на печать: bar.prop: 10, foo.prop: 2.Внутри функции f, obj1 содержит тот же адрес памяти, что и bar, а obj2 содержит тот же адрес памяти, что и foo.Однако затрагивается только строка, потому что внутри f отражаются только изменяющиеся элементы объектов, а присвоение obj2 = {prop: 20}; влияет только на локальную переменную obj2, а не foo.

Другими словами, the "value" is a reference to an object означаетизменение членов влияет на объект , на который есть ссылка , но назначение влияет только на локальную переменную.

1 голос
/ 28 февраля 2012

Это верно.Когда вы назначаете переменную объекту, вы действительно создаете вторую ссылку на этот объект.В первом случае вы назначаете bar для указания на строку, на которую указывает foo, но затем вы меняете на что указывает bar при переназначении bar.

Во втором примере вы присваиваете bar новому объекту, затем указываете foo на тот же объект, затем переназначаете bar на строку.foo все еще направлен на тот же объект.

Думайте об этом так: bar = "something" означает изменение того, что bar указывает на , не изменяя фактический объект {} настрока.

Эта статья является довольно хорошим объяснением того, что вы видите.Однако я ищу еще лучшие / более авторитетные ссылки.

0 голосов
/ 28 февраля 2012

В первом коде вы определяете бар Var как переменную.

во втором коде вы определяете его как объект.

Переменные занимают место в памяти, поэтому, когда выопределить foo из bar, он будет того же типа, что и переменная, и зарезервирует новую ячейку памяти;и когда вы используете оператор равенства, вы заменяете содержимое данных этой переменной.

Объект во втором примере кода при инициализации будет указывать (как указатель) на область памяти, которая будет содержать данные этого объекта;и когда вы определяете foo из bar, он будет того же типа, что и объект, и будет указывать на ту же область памяти;поэтому изменение значения одного из этих двух эталонных объектов отразится на другом.

...