Почему this.tail изменяет свойство this.head в моем классе Linkedlist?

Рассмотрим класс LinkedList, который имитирует структуру данных Linkedlist, как показано ниже:

class LinkedList {
  constructor(value) {
    this.head = {
      value: value,
      next: null
    };
    this.tail = this.head;
    this.length = 1;
  }
  append(value) {
    const newNode = {
      value: value,
      next: null
    }
    this.tail.next = newNode; // why does this change head.next ?
    this.tail = newNode;
    this.length++;
    return this;
  }
}

let myLinkedList = new LinkedList(10);
myLinkedList.append(5);

вывод журнала

LinkedList {
  head: { value: 10, next: { value: 5, next: null } },
  tail: { value: 5, next: null },
  length: 2
}

Я вижу, что this.tail.next также изменит следующее свойство tail (тогда this.tail = newNode переназначит tail на newNode). Я не понимаю, почему this.tail.next также изменит следующее свойство this.head?

Кроме того, при добавлении другого числа в список myLinkedList.append(16) он продолжает обновлять следующее свойство head, как показано ниже:

LinkedList {
  head: { value: 10, next: { value: 5, next: [Object] } },
  tail: { value: 16, next: null },
  length: 3
}

Может быть, возможная причина связана с конструктором, в котором я определяю this.tail = this.head? Но я не совсем уверен, так как этот только присваивает значение «голова к хвосту».

Подводя итог, мой вопрос: почему this.tail.next = newNode меняет следующее свойство головы? Кроме того, почему при добавлении другого значения изменяется head.next.next и так далее?

«Может быть, возможная причина связана с конструктором, в котором я определяю this.tail = this.head?» - да, конечно, причина в этом: оба свойства теперь содержат одну и ту же ссылку на объект, а затем вы меняете свойство .next этого объекта, на который ссылаются из обоих мест.

Bergi 06.04.2021 12:47

Первое добавление - это ожидал для обновления заголовка (потому что в начале заголовок является хвост). Второе дополнение не обновляет head, это просто console.info, который представляет его таким образом. То есть ваш код в порядке.

georg 06.04.2021 12:49

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

Bergi 06.04.2021 12:53

Это не мой код (да, он должен работать таким образом, но я не понимал, как он работает, поэтому я спросил: D (немного подумав, tbh)) Так что на самом деле это просто ссылка на объект. Контрольный объект головы присваивается хвосту. когда я использую tail.next, он также обновляет объект, на который он ссылается, который является head.next. Верно?

aanhlle 06.04.2021 13:06
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
4
34
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Когда конструктор запущен, this.tail и this.head ссылаются на один и тот же объект, поэтому любое присвоение, которое вы делаете для this.tail.next, отображается в this.head, поскольку это действительно ссылка на тот же объект, который мутируется.

Это может помочь визуализировать это. После запуска конструктора возникает такая ситуация:

     this.head
      ↓          
    ┌───────────┐
    │ value: 10 │
    │ next: null│
    └───────────┘
      ↑
     this.tail

Затем append(5) сначала создаст новый узел:

     this.head        newNode
      ↓                ↓
    ┌───────────┐    ┌───────────┐
    │ value: 10 │    │ value: 5  │
    │ next:null │    │ next:null │
    └───────────┘    └───────────┘
      ↑
     this.tail

Затем выполняется this.tail.next = newNode;, который является модификацией этого свойства next в первом объекте:

     this.head        newNode
      ↓                ↓
    ┌───────────┐    ┌───────────┐
    │ value: 10 │    │ value: 5  │
    │ next: ———————→ │ next:null │
    └───────────┘    └───────────┘
      ↑
     this.tail

Так что, действительно, это тоже меняет this.head.next ... потому что это то же самое свойство.

Затем выполняется this.tail = newNode;:

     this.head        newNode
      ↓                ↓
    ┌───────────┐    ┌───────────┐
    │ value: 10 │    │ value: 5  │
    │ next: ———————→ │ next:null │
    └───────────┘    └───────────┘
                       ↑
                      this.tail

При следующем вызове append свойство next объекта второй будет обновлено, и мы получим:

     this.head                         newNode
      ↓                                 ↓
    ┌───────────┐    ┌───────────┐    ┌───────────┐
    │ value: 10 │    │ value: 5  │    │ value: 16 │
    │ next: ———————→ │ next: ———————→ │ next:null │
    └───────────┘    └───────────┘    └───────────┘
                                        ↑
                                       this.tail

И да, это изменение также можно отследить от this.head, потому что ... это связанный список ... так что можно отследить должен. Поскольку каждое свойство next относится к следующему узлу, вы можете найти свой путь от head к любому из узлов.

Спасибо за вашу простую для понимания иллюстрацию! Я очень ценю это!

aanhlle 07.04.2021 05:32

Другие вопросы по теме