Итак, я на днях поигрался, просто чтобы увидеть, как именно массовое назначение работает в 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);
(Я подозреваю, что JavaScript обрабатывает примитивы, такие как строки и целые числа, иначе, чем хеши. Хэши возвращают указатель, в то время как "базовые" примитивы возвращают свою копию)
javascript
Крис Ллойд
источник
источник
Ответы:
В первом примере вы устанавливаете свойство существующего объекта. Во втором примере вы назначаете новый объект.
a
иb
теперь являются указателями на один и тот же объект. Итак, когда вы это сделаете:Он также устанавливается,
b.foo
посколькуa
иb
указывает на тот же объект.Тем не мение!
Если вы сделаете это вместо этого:
вы говорите, что сейчас это
a
указывает на другой объект. Это не влияет на то, чтоa
указывалось ранее.В JavaScript присвоение переменной и присвоение свойства - это две разные операции. Лучше всего рассматривать переменные как указатели на объекты, и когда вы присваиваете переменную напрямую, вы не изменяете никаких объектов, а просто перенаправляете свою переменную на другой объект.
Но присвоение свойства, например
a.foo
, изменит объект, на которыйa
указывает. Это, конечно, также изменяет все другие ссылки, указывающие на этот объект, просто потому, что все они указывают на один и тот же объект.источник
var foo = new String('foo');
, то это был бы строковый объект (иtypeof
это подтвердит). Но если вы объявите его с помощью строкового литерала, тогда они будут строковыми примитивами. См .: developer.mozilla.org/en/JavaScript/Reference/Global_Objects/…На ваш вопрос уже был дан удовлетворительный ответ от Squeegy - он не имеет ничего общего с объектами и примитивами, но с переназначением переменных и установкой свойств в том же объекте, на который имеется ссылка.
Кажется, что в ответах и комментариях много путаницы с типами JavaScript, поэтому вот небольшое введение в систему типов JavaScript:
В JavaScript есть два принципиально разных типа значений: примитивы и объекты (и нет ничего похожего на «хеш»).
Строки, числа и логические значения, а также
null
иundefined
примитивы, объекты все , что может иметь свойства. Даже массивы и функции являются обычными объектами и поэтому могут иметь произвольные свойства. Они отличаются только внутренним свойством [[Class]] (функции дополнительно имеют свойство, называемое [[Call]] и [[Construct]], но это подробности).Причина того, что примитивные значения могут вести себя как объекты, заключается в автобоксировании, но сами примитивы не могут содержать никаких свойств.
Вот пример:
В результате будет выведено
undefined
:a
содержит примитивное значение, которое будет повышено до объекта при назначении свойстваfoo
. Но этот новый объект немедленно отбрасывается, поэтому значениеfoo
теряется.Подумайте об этом так:
источник
Вы более или менее правы, за исключением того, что то, что вы называете «хешем», на самом деле является сокращенным синтаксисом объекта.
В первом примере a и b оба относятся к одному и тому же объекту. Во втором примере вы меняете a, чтобы ссылаться на что-то еще.
источник
вот мой вариант ответа:
источник
Вы устанавливаете a, чтобы он указывал на новый строковый объект, а b продолжал указывать на старый строковый объект.
источник
В первом случае вы изменяете какое-то свойство объекта, содержащегося в переменной, во втором случае вы присваиваете переменной новое значение. Это принципиально разные вещи. Переменные
a
иb
не связаны каким-то магическим образом посредством первого присваивания, они просто содержат один и тот же объект. То же самое и во втором примере, пока вы не присвоитеb
переменной новое значение .источник
Разница между простыми типами и объектами.
Все, что является объектом (например, массив или функция), передается по ссылке.
Все, что является простым типом (например, строка или число), копируется.
У меня всегда есть под рукой функция copyArray, поэтому я могу быть уверен, что не создаю кучу псевдонимов для одного и того же массива.
источник