各位,
在熟悉 TypeScript 时,我在让简单的 LinkedList 实现正常工作时遇到了严重的麻烦。
这是源代码 - 我将在下面详细描述问题。
class LinkedList<ListType> {
firstElement:ListItem<ListType> = null;
/**
* add Element in Front of List
*/
addElementFirst(element: ListType) {
var newItem:ListItem<ListType> = new ListItem<ListType>();
newItem.setElement(element);
newItem.setNextItem(this.firstElement);
this.firstElement = newItem;
}
/**
* add Element at End of List;
*/
addElementLast(element: ListType) {
var newItem:ListItem<ListType> = new ListItem<ListType>();
newItem.setNextItem(null);
newItem.setElement(element);
//find last Element;
var li:ListItem<ListType> = this.firstElement; //THIS IS
while (li!=null) li=li.getNextItem(); //WHERE IT
li = newItem; //BREAKS!
}
dumpListContents() {
var li:ListItem<ListType> = this.firstElement;
var i:number = 0;
while (li!=null) {
console.log(i+". "+li.getElement());
li=li.getNextItem();
i++
}
}
}
class ListItem<ListType> {
private element:ListType;
private nextItem: ListItem<ListType>;
setElement(element:ListType) {
this.element=element;
}
getElement():ListType {
return this.element;
}
setNextItem(nextItem:ListItem<ListType>) {
this.nextItem=nextItem;
}
getNextItem():ListItem<ListType> {
return this.nextItem;
}
}
var foo:LinkedList<string> = new LinkedList<string>();
var bar:LinkedList<string> = new LinkedList<string>();
console.log("Playing with foo");
foo.addElementFirst("first");
foo.addElementFirst("second");
foo.addElementFirst("third");
foo.dumpListContents();
console.log("Playing with bar");
bar.addElementLast("first");
bar.addElementLast("second");
bar.addElementLast("third");
bar.dumpListContents();
上面的代码使用泛型实现了一个简单的类型化 LinkedList,就像在其他 OO 语言中一样,代码行很长。问题是 addElementFirst 工作得很好,但 addElementLast 却严重失败。
为什么会这样呢?我强烈的假设是作业
var li:ListItem<ListType> = this.firstElement; //THIS IS
while (li!=null) li=li.getNextItem(); //WHERE IT
li = newItem; //BREAKS!
为局部变量分配一个值(而不是传递引用!),因此,随后对 addElementLast 中的数据结构所做的所有更改都是局部的,并且不会对原始数据结构进行操作。生成的 JS 代码如下所示并证实了这一假设:
LinkedList.prototype.addElementLast = function (element) {
var newItem = new ListItem();
newItem.nextItem = null;
newItem.element = element;
//find last Element;
var li = this.firstElement;
while (li != null)
li = li.nextItem;
li = newItem;
};
从理论上讲,我担心我认为赋值语义与 Java 存在很大不同,在 Java 中,模拟代码可以工作,因为所有赋值都将仅使用引用进行。
有没有一种简单的概念方法可以解决这个问题?我可以强制底层 JavaScript 严格使用引用吗?
最诚挚的问候, 埃利亚斯
最佳答案
您所做的就是将 newItem
分配给局部变量 li
//find last Element;
var li:ListItem<ListType> = this.firstElement;
while (li!=null) li=li.getNextItem();
//At this point, li is null. All you're doing is assigning the newItem to your variable
li = newItem;
您需要做的是在循环到最后一个元素后使用您的 setNextItem
方法:
//find last Element;
var li:ListItem<ListType> = this.firstElement;
while (li.getNextItem()!=null) li=li.getNextItem();
//At this point, li is the last element
li.setNextItem(newItem);
请注意,当下一项为空时,我们不会将 li 分配给它,因此它仍然指向列表中的最后一项。最后,如果列表没有任何元素,我们需要处理:
//find last Element;
if (this.firstElement == null) {
this.firstElement = newItem;
} else {
var li:ListItem<ListType> = this.firstElement;
while (li.getNextItem()!=null) li=li.getNextItem();
//At this point, li is the last element
li.setNextItem(newItem);
}
关于javascript - TypeScript 引用调用困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27041333/