Почему результат отличается от того, что я ожидаю?

#javascript

#javascript

Вопрос:

Начальное понимание:
Я где-то читал, что когда ссылочные типы данных (объекты) присваиваются переменной A, переменная содержит адрес памяти объекта. И когда variableA присваивается variableB, variableB также получает копию этого адреса в памяти. Т.е. он ссылается на тот же объект. Мне понравилось это определение.

 a = {color: "red"};

b = a;

//a = {color: "red"};

console.lo&(a);
console.lo&(b); 
console.lo&(a === b);  

Просмотр приведенного выше фрагмента подтверждает эту идею. Это выглядит как копия адреса памяти объекта, в a котором хранятся ссылки a . Когда a присваивается b , b получает этот «адрес» и ссылается на тот же объект.

Однако это разваливается при a повторной инициализации ( a = {color: "red"}; ):

 a = {color: "red"};

b = a;

a = {color: "red"};

console.lo&(a);
console.lo&(b); 
console.lo&(a === b);  

Я ожидал, что a === b все равно вернется true . Для меня это противоречит моему «первоначальному пониманию», потому что, конечно, если бы b мне был присвоен тот же адрес в памяти, который a является «меткой», b он «обновился» бы и был меткой того же, что a является меткой of .

Как мне пересмотреть свое понимание происходящего?

Комментарии:

1. a = {color: "red"}; создает совершенно новый объект в правой части = и присваивает a ссылку на этот совершенно новый объект. Новый объект явно не совпадает со старым объектом. Каждое выражение инициализатора объекта создает уникальный новый объект.

2. @Pointy Взгляните на мое «потенциальное пересмотренное понимание». Я знаю, что новый объект a не совпадает со старым объектом a . ( Я надеюсь, что это то, что a означает быть «повторно инициализированным»!) Мой вопрос заключался в том, b будет ли «догонять» и по-прежнему ли быть меткой того, что a является меткой.

3. вы сами это объяснили. b = a; копирует адрес памяти, а не объект. итак, когда вы создаете новый объект, он будет находиться в новой ячейке памяти.

4. @tonitone120 нет — присвоение b результатам не приводит к долговременной связи в между двумя переменными. Ссылка назначена, и все.

5. Спасибо @Pointy, я думаю, что теперь это немного проясняется. Я был бы удовлетворен, если бы мог описать ситуацию следующим образом: b = a средство b сохраняет точный адрес в памяти, который a был захвачен — в данный текущий момент . Между двумя переменными нет долгосрочной взаимосвязи. a может быть повторно инициализирован и указывать на другую ячейку памяти; в то же время, b все равно будет указывать на старую. Пока что-то ссылается на это старое местоположение, оно будет сохраняться.

Ответ №1:

Сначала вы создаете объект {color: "red"} и устанавливаете на него ссылку из a .
Чем вы позволяете b=a , при этом ссылка из a копируется в b, поэтому обе ссылаются на один и тот же объект.
В-третьих, вы создаете совершенно новый объект {color: "red"} и устанавливаете на него ссылку для a . Итак, теперь у a есть новая ссылка на него, но у b все еще есть старая ..
Если вы сейчас сравните a===b , будет проверено, идентичны ли ссылки, и это не так, так что это false.

Комментарии:

1. 1 для » ссылка скопирована «. Это не ссылка на a .

Ответ №2:

Из этой документации о равенстве объектов вы можете увидеть это:


Object.is() определяет, являются ли два значения одним и тем же значением. Два значения одинаковы, если выполняется одно из следующих:

  • оба не определены
  • оба null
  • оба истинны или оба ложны
  • обе строки одинаковой длины с одинаковыми символами в одинаковом порядке
  • оба объекта являются одними и теми же (означает, что оба объекта имеют одинаковую ссылку)
  • оба числа и
    • оба 0
    • оба -0
    • оба NaN
    • или оба ненулевых, и оба не NaN, и оба имеют одинаковое значение

[…] Это также не то же самое, что быть равным в соответствии с оператором ===. Оператор === (а также оператор ==) обрабатывает числовые значения -0 и 0 как равные и обрабатывает число.NaN как не равный NaN


В случае, который вы опубликовали, выделенное условие не выполняется, поскольку новое назначение создает новый [сложный] объект: хотя значения между экземплярами одинаковы, их идентификаторы — нет.

Цель этой цитаты — проиллюстрировать сравнение объектов в JS различными способами, поскольку из вопросов ясно, что это ключевой момент, задаваемый пользователем.

Комментарии:

1. Просто чтобы уточнить: вы не используете напрямую Object.is() , но это иллюстрирует, как JS оценивает равенство объектов.

2. в итоге вы на самом деле не хотите использовать == для определения того, похожи ли объекты.

3. Непонятно, почему вы цитируете документацию о том, Object.is когда используется OP === ?

4. Я сказал в своем первом комментарии: чтобы проиллюстрировать равенство точек отсчета. В документации также разъясняются различия с ===

Ответ №3:

Когда вы пишете b = a , вы заявляете, что можете вызывать a object либо a , либо b . Другими словами, вы даете второе имя a , то есть b .

Если вы присваиваете a новому объекту (открывая скобки с ключами {} ), a это уже не тот объект, что b , у них разные начала и идентификаторы.

Если вы хотите сравнить объекты по их содержимому, вы можете выполнить следующее:

 var a = { color: 'red' };
var b = { color: 'red' };
console.lo&( JSON.strin&ify(a) );
console.lo&( JSON.strin&ify(b) );

Object.prototype.equals_obj = function(second) {
  return JSON.strin&ify(this) == JSON.strin&ify(second);
}

console.lo&( a.equals_obj(b) );