Как назначение переменной работает в JavaScript?
Таким образом, я играл на днях, чтобы посмотреть, как работает массовое задание в JavaScript.
Сначала я попробовал этот пример в консоли:
a = b = {};
a.foo = 'bar';
console.log(b.foo);
Результатом стал "бар", отображаемый в предупреждении. Это справедливо, a
и b
- это просто псевдонимы одного и того же объекта. Тогда я подумал: как я могу сделать этот пример более простым.
a = b = 'foo';
a = 'bar';
console.log(b);
Это почти то же самое, не так ли? На этот раз он возвращает foo
не bar
как я ожидал бы от поведения первого примера.
Почему это происходит?
NB Этот пример может быть упрощен еще более с помощью следующего кода:
a = {};
b = a;
a.foo = 'bar';
console.log(b.foo);
a = 'foo';
b = a;
a = 'bar';
console.log(b);
Ответы
Ответ 1
В первом примере вы устанавливаете свойство существующего объекта. Во втором примере вы назначаете совершенно новый объект.
a = b = {};
a
и b
теперь указывают на один и тот же объект. Поэтому, когда вы это делаете:
a.foo = 'bar';
Он также устанавливает b.foo
так как a
и b
указывают на один и тот же объект.
Однако!
Если вы сделаете это вместо этого:
a = 'bar';
Вы говорите, что указывает на другой объект в настоящее время. a
Это не имеет никакого влияния на то, что указал ранее. a
В JavaScript назначение переменной и присвоение свойства - это две разные операции. Лучше всего думать о переменных как о указателях на объекты, а когда вы назначаете непосредственно переменной, вы не изменяете какие-либо объекты, просто переставляя свою переменную на другой объект.
Но присваивание свойства, например a.foo
, изменит объект, a
указывает точка. Это, конечно же, также изменяет все другие ссылки, указывающие на этот объект, просто потому, что все они указывают на один и тот же объект.
Ответ 2
Ваш вопрос уже удовлетворительно ответил Squeegy - он не имеет ничего общего с объектами и примитивами, но с переназначением переменных и настроек свойств в том же ссылочном объекте.
В ответах и комментариях есть много путаницы в отношении типов JavaScript, поэтому здесь представлено небольшое введение в систему типа JavaScript:
В JavaScript есть два принципиально разных вида значений: примитивы и объекты (и нет такой вещи, как хэш).
Строки, числа и булевы, а также null
и undefined
являются примитивами, объекты - все, что может иметь свойства. Даже массивы и функции являются регулярными объектами и поэтому могут содержать произвольные свойства. Они просто отличаются внутренним свойством [[Class]] (функции дополнительно имеют свойство, называемое [[Call]] и [[Construct]], но эй, эти детали).
Причина, по которой примитивные значения могут вести себя как объекты, связана с автобоксированием, но сами примитивы не могут содержать никаких свойств.
Вот пример:
var a = 'quux';
a.foo = 'bar';
document.writeln(a.foo);
Это приведет к выходу undefined
: a
содержит примитивное значение, которое присваивается объекту при назначении свойства foo
. Но этот новый объект немедленно отбрасывается, поэтому теряется значение foo
.
Подумайте об этом так:
var a = 'quux';
new String(a).foo = 'bar'; // we never save this new object anywhere!
document.writeln(new String(a).foo); // a completly new object gets created
Ответ 3
Вы более или менее корректны, за исключением того, что то, что вы называете "хешем", на самом деле является просто сокращенным синтаксисом для объекта.
В первом примере a и b оба относятся к одному и тому же объекту. Во втором примере вы меняете a, чтобы ссылаться на что-то еще.
Ответ 4
вот моя версия ответа:
obj = {a:"hello",b:"goodbye"}
x = obj
x.a = "bonjour"
// now obj.a is equal to "bonjour"
// because x has the same reference in memory as obj
// but if I write:
x = {}
x.a = obj.a
x.b = obj.b
x.a = "bonjour"
// now x = {a:"bonjour", b:"goodbye"} and obj = {a:"hello", b:"goodbye"}
// because x points to another place in the memory
Ответ 5
Вы устанавливаете a для указания на новый объект строки, тогда как b продолжает указывать на старый объект строки.
Ответ 6
В первом случае вы изменяете какое-либо свойство объекта, содержащегося в переменной, во втором случае вы назначаете новое значение переменной. Это принципиально разные вещи. Переменные a
и b
не связаны каким-то магическим образом с помощью первого присваивания, они просто содержат один и тот же объект. Это также случай во втором примере, пока вы не назначите новое значение переменной b
.
Ответ 7
Разница между простыми типами и объектами.
Все, что объект (например, массив или функция) передается по ссылке.
Все, что скопирован простой тип (например, строка или число).
У меня всегда есть функция copyArray, поэтому я могу быть уверен, что не создаю кучу псевдонимов в один и тот же массив.