JavaScript не может изменить ссылку на указатель [duplicate]

Вы можете использовать linq для сравнения ключей и значений:

  public bool Compare & lt; TKey, TValue & gt; (Dictionary & lt; TKey, TValue & gt; dict1, Dictionary & lt; TKey, TValue dict2) {IEqualityComparer & lt;  ; TValue & GT;  valueComparer = EqualityComparer & lt; TValue & gt; .Default;  return dict1.Count == dict2.Count & amp; & amp; & amp;  dict1.Keys.All (key = & gt; dict2.ContainsKey (key) & amp; valueComparer.Equals (dict1 [key], dict2 [key]));  }  
58
задан Philip Walton 19 April 2013 в 06:08
поделиться

5 ответов

Следуя вашему примеру, строка за строкой:

a = {}

a теперь ссылается на новый объект.

b = a;

b теперь ссылается на тот же объект, что a Рекомендации. Обратите внимание, что это не ссылается на a.

a['one'] = {};

Новый объект теперь имеет индекс 'one', который ссылается на другой новый объект.

Когда вы делаете

a = a['one'];

Вы устанавливаете a для обозначения a['one'], который является тем новым созданным вами объектом, когда вы делали a['one'] = {}. b по-прежнему ссылается на объект, созданный с помощью a = {}.

Вы путаете проблему, когда говорите: «a потерял ссылку на b», потому что a не ссылается на b, и наоборот. a и b относятся к объектам , и их можно заставить ссылаться на другие объекты. Например:

С помощью a = {}; b = a вы получаете

a
 \
  \
   { }
  /
 /
b

Затем с a['one'] = {} вы получаете

a
 \
  \
   { one: { } }
  /
 /
b

Затем с помощью a = a['one'] вы get

a - - - - 
          \
   { one: { } }
  /
 /
b
195
ответ дан Seth Carnegie 16 August 2018 в 10:51
поделиться
  • 1
    Иногда простота a = {} теряет ясность указателей. Если это помогает, когда вы читаете {} в своей голове, замените это на «новый объект ()». и помните, что он создает новую ссылку. – Will Shaver 30 November 2011 в 00:11
  • 2
    отличное использование искусства ASCII! – Genia S. 30 November 2011 в 00:13
  • 3
    +1 для действительно потрясающего и полезного объяснения! – Zlatko 30 November 2011 в 00:13
  • 4
    Awww ... эпический провал. Я публикую то, что (я думал) было отличным способом объяснить это, тогда я вижу эту визуализацию ... * sigh * ... +1. – riwalk 30 November 2011 в 00:24

Объекты в Javascript могут существовать сами по себе, не нуждаясь в имени. Например:

{}

- новый экземпляр словарного объекта.

a = {};

создает новый объект словаря и ссылается на a. Теперь

b = a;

делает b ссылкой на один и тот же базовый объект. Затем вы можете сделать точку a в другом месте:

a = "hi";

и b все еще указывает на тот же словарь, что и раньше. Поведение b не связано с тем, как вы изменяете то, что указывает a.

6
ответ дан Greg Hewgill 16 August 2018 в 10:51
поделиться

Подумайте об анонимном объекте, поскольку он сам имеет имя:

a = {}; // The variable "a" now points to (holds) an anonymous object.
b = a; // "b" points to the same anonymous object held by "a".
a = 123; // "a" now holds some other value.
b; // "b" still holds the anonymous object.

Ключ должен помнить, что переменные содержат ссылки на objects , а не ссылки на другие переменные. И тот же объект может ссылаться на любое количество переменных.

8
ответ дан maerics 16 August 2018 в 10:51
поделиться
  • 1
    +1: Этот последний абзац был действительно хорошим способом поставить его. – nnnnnn 30 November 2011 в 01:15

Насколько я знаю, вы перезаписали, поэтому я думаю, что двигатель сохраняет его в другом пространстве памяти, тогда как b все еще указывает на адрес памяти старого a (который каким-то образом не разрушается).

0
ответ дан R01010010 16 August 2018 в 10:51
поделиться

: P Ты спускаешься в мельчайшие детали, и я рад, что ты спросил, как ты будешь мудрее к концу.

Не смотрите на это с точки зрения указателей, потому что Я думаю, это то, где вы запутались. Подумайте об этом скорее с точки зрения кучи (или просто «памяти», если хотите) и таблицы символов.

Давайте начнем с ввода первых нескольких строк вашего кода:

var a, b;

a = {}
b = a;

Вы сделали здесь один объект в куче и два символа в таблице символов. Это выглядит примерно так:


Таблица символов :

+--------+-----------------+
| Symbol | Memory Location |
+--------+-----------------+
|      a |        0x400000 |
+--------+-----------------+
|      b |        0x400000 |
+--------+-----------------+

Куча :

+----------+-----------------+
| Location | Value           |
+----------+-----------------+
| 0x400000 | <object val 1>  |
+----------+-----------------+

.


Здесь интересны вещи: у объектов есть свои «таблички символов» (обычно это просто хеш-таблицы, но называть их таблицей символов можно сделать более ясным).

Теперь, после вашего следующего утверждения, у вас есть 3 вещи: таблица глобального символа, таблица символов <object val 1> и куча.

Запустите следующую строку:

a['one'] = {}

И теперь все выглядит так:


Глобальная таблица символов :

+--------+-----------------+
| Symbol | Memory Location |
+--------+-----------------+
|      a |        0x400000 |
+--------+-----------------+
|      b |        0x400000 |
+--------+-----------------+

<object val 1> Таблица символов

+--------+-----------------+
| Symbol | Memory Location |
+--------+-----------------+
|    one |        0x400004 |
+--------+-----------------+

Куча :

+----------+-----------------+
| Location | Value           |
+----------+-----------------+
| 0x400000 | <object val 1>  |
+----------+-----------------+
| 0x400004 | <object val 2>  |     <---we created a new object on the heap
+----------+-----------------+

.


Теперь вы выполнили следующий код:

a = a['one'];

Это, должно быть, кажется тривиальным изменением. Результат:


Таблица глобальных символов :

+--------+-----------------+
| Symbol | Memory Location |
+--------+-----------------+
|      a |        0x400004 |
+--------+-----------------+
|      b |        0x400000 |
+--------+-----------------+

Символьная таблица <object val 1>

+--------+-----------------+
| Symbol | Memory Location |
+--------+-----------------+
|    one |        0x400004 |
+--------+-----------------+

Куча :

+----------+-----------------+
| Location | Value           |
+----------+-----------------+
| 0x400000 | <object val 1>  |
+----------+-----------------+
| 0x400004 | <object val 2>  | 
+----------+-----------------+

.


Следуя ячейкам памяти в куче, мы, надеюсь, сделаем это ясно, почему вы получили результат, который вы сделали.

Теперь все становится еще интереснее, потому что теперь вы делаете:

a['two'] = 2;

Хорошо, давайте сделаем это шаг за шагом.

  • a указывает на ячейку памяти 0x400004, которая содержит <object val 2>
  • <object val 2> - пустой объект, поэтому его таблица символов начинает пуст
  • Запустив эту строку, мы добавим переменную «two» в таблицу символов <object val 2>.

Если вы еще не устали смотреть на эти диаграммы, вы будете быть. Теперь все выглядит так:


Таблица глобальных символов :

+--------+-----------------+
| Symbol | Memory Location |
+--------+-----------------+
|      a |        0x400004 |
+--------+-----------------+
|      b |        0x400000 |
+--------+-----------------+

Символьная таблица <object val 1>

+--------+-----------------+
| Symbol | Memory Location |
+--------+-----------------+
|    one |        0x400004 |
+--------+-----------------+

<object val 2> Символьная таблица

+--------+-----------------+
| Symbol | Memory Location |
+--------+-----------------+
|    two |        0x400008 |
+--------+-----------------+

Куча :

+----------+-----------------+
| Location | Value           |
+----------+-----------------+
| 0x400000 | <object val 1>  |
+----------+-----------------+
| 0x400004 | <object val 2>  | 
+----------+-----------------+
| 0x400008 | 2 (literal val) |    <-- yes, even integers are stored on the heap
+----------+-----------------+        in JavaScript.

.


Если вы усердно занимаете время, чтобы следить за местоположениями памяти, вы увидите, что ваш браузер отобразил правильный вывод.

45
ответ дан riwalk 16 August 2018 в 10:51
поделиться
  • 1
    ha, ваша диаграмма намного более подробно, чем моя (я просто рисую диаграммы со стрелками). +1 – Seth Carnegie 30 November 2011 в 00:26
  • 2
    @SethCarnegie, да, но вы получаете ту же самую точку в гораздо меньшем пространстве. – riwalk 30 November 2011 в 00:27
  • 3
    Есть ли какой-либо инструмент для отображения местоположений переменной памяти JavaScript? Или, в противном случае, какой-либо активный способ отладки / отладки памяти? – P.Brian.Mackey 30 November 2011 в 00:33
  • 4
    @ P.Brian.Mackey ... не то, что я знаю. Это хороший способ подумать об этом, но современные JavaScript-движки оптимизируются до крайности, поэтому маловероятно, что вы сможете иметь инструмент, который даст вам картину именно так. (Например: таблицы символов отменяются в пользу смещений, когда это возможно, и фактическая структура объектов может быть намного сложнее с использованием скрытых классовых структур, среди прочего ... его длинное отверстие кролика ... придерживаться ментальной модели на данный момент: P) – riwalk 30 November 2011 в 00:36
Другие вопросы по тегам:

Похожие вопросы: