Javascript 为什么this.tail会更改Linkedlist类中this.head的属性?

Javascript 为什么this.tail会更改Linkedlist类中this.head的属性?,javascript,class,oop,linked-list,this,Javascript,Class,Oop,Linked List,This,考虑一个模仿LinkedList数据结构的LinkedList类,如下所示: 类链接列表{ 构造函数(值){ 这个头={ 价值:价值, 下一个:空 }; this.tail=this.head; 这个长度=1; } 附加(值){ 常数newNode={ 价值:价值, 下一个:空 } this.tail.next=newNode;//为什么会更改head.next? this.tail=newNode; 这个.length++; 归还这个; } } 让myLinkedList=newLinkedL

考虑一个模仿LinkedList数据结构的LinkedList类,如下所示:

类链接列表{
构造函数(值){
这个头={
价值:价值,
下一个:空
};
this.tail=this.head;
这个长度=1;
}
附加(值){
常数newNode={
价值:价值,
下一个:空
}
this.tail.next=newNode;//为什么会更改head.next?
this.tail=newNode;
这个.length++;
归还这个;
}
}
让myLinkedList=newLinkedList(10);
myLinkedList.append(5);
日志输出

LinkedList{
head:{value:10,next:{value:5,next:null},
尾部:{value:5,next:null},
长度:2
}
我看到
this.tail.next
也将更改tail的next属性(然后
this.tail=newNode
将tail重新分配给newNode)。我不明白的是为什么
this.tail.next
还会更改this.head的next属性

此外,当将另一个数字追加到列表
myLinkedList.append(16)
时,它会不断更新head的下一个属性,如下所示:

LinkedList{
head:{value:10,next:{value:5,next:[Object]},
尾部:{value:16,next:null},
长度:3
}
也许一个可能的原因与我定义的构造函数有关,在这里我定义了
this.tail=this.head
?但我不是很确定,因为这一个只分配头到尾的值


总之,我的问题是为什么
this.tail.next=newNode
会更改头部的next属性?另外,当附加另一个值时,为什么会更改head.next.next等等?

当构造函数运行时,
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
到任何节点的路径。

“可能有一个可能的原因与我定义
this.tail=this.head
的构造函数有关。”-是的,当然这就是原因:两个属性现在都拥有相同的对象引用,然后您将更改从两个位置引用的对象的
。next
属性。第一个附加将更新head(因为开头的head是tail)。第二个附加没有更新
,它只是
控制台.log
以这种方式表示它。也就是说,你的代码很好。(你的代码唯一奇怪的地方是链表总是至少包含一个元素,不能为空)这不是我的代码(是的,它应该是这样工作的,但我不明白它是如何工作的,所以我问:D(经过一些思考tbh)),所以实际上它只是对象引用。头部的参照对象指定给尾部。当我执行
tail.next
时,它还会更新它引用的对象,即head.next。是吗?谢谢你简单易懂的说明!我真的很感激!