在 ES2015 中使用生成器作为迭代器 class
Using generator as an iterator in an ES2015 class
Please find the complete code example in action here.
我正在尝试将生成器用作迭代器并将其与 toString
中的 for..of
循环结合使用,但不知何故它不起作用。
这是我的(生成器)迭代器的样子 -
*[Symbol.iterator]() {
let temp = this.head;
while (temp) {
yield temp.item;
temp = temp.next;
}
}
然后我尝试在 toString
方法中使用它,如下所示 -
[Symbol.toStringTag]() {
for (const temp of this) {
return `${temp} -> `;
}
}
我想象使用 for..of
循环和 this
引用应该调用迭代器,但它没有。这可以通过控制台日志中缺少 Iterator called
语句来观察,并且使用默认 toString
打印对象。
有什么我遗漏的吗?
你有几个大问题
Symbol.toStringTag
应该是解析为字符串而不是函数的 属性。这意味着
[Symbol.toStringTag]() {
应该是
get [Symbol.toStringTag]() {
因此 属性 是一个 getter,它将 return 一个访问字符串。
console.log(list)
不调用.toString()
,所以需要console.log(list.toString())
.
您会注意到,list.toString() === "[object 1 -> ]"
,也可能不是您想要的。 toStringTag
被附加到另一个字符串中,有点像
`[object ${this[Symbol.toStringTag]}]`
所以如果你真的想要一个漂亮的字符串输出,你可能只想要
toString() {
作为您的方法,跳过 toStringTag
.
如果你试图序列化整个列表,你的循环就没有意义,因为你 return
是列表中的第一个项目,而从不费心处理其余的的项目。
所以最后,我可能会把你想做的写成
toString() {
let result = "";
for (let item = this.head; item; item = item.next) {
if (result) result += ' -> ';
result += item.item;
}
return result;
}
I would imagine that using for..of
loop with this reference should call the iterator but it doesn't.
确实如此。您只是从未在示例中调用该方法。
the object is printed to console using default toString
instead
它不是,它是使用控制台自己的对象表示打印的(在 babeljs.io repl 上,它似乎是 .constructor.name
和 JSON.stringify
的混合)。
… toString
method as shown below - [Symbol.toStringTag]() { …
没有。 Symbol.toStringTag
在被 Object.prototype
继承时用作标准 toString
表示的一部分。它不是一种方法,而是一个普通值(您可以使用 getter,但您不应该使用)。
如果要实现自定义 toString
方法,实际实现 that.
这是一个更新的示例,可以满足您的需求:
class SLListNode {
constructor(item, next) {
this.item = item;
this.next = next;
}
toString() {
return `${this.item} -> ${this.next}`;
}
}
class SinglyLinkedList {
constructor() {
this.length = 0;
this.head = null;
}
addFirst(item) {
this.head = new SLListNode(item, this.head);
this.length++;
}
*[Symbol.iterator]() {
console.log('Iterator called');
let temp = this.head;
while (temp) {
yield temp.item;
temp = temp.next;
}
}
getLength() {
return this.length;
}
toString() {
return `{ ${this.head.toString()} }`;
}
}
SinglyLinkedList.prototype[Symbol.toStringTag] = "LinkedList";
const list = new SinglyLinkedList();
list.addFirst(3);
list.addFirst(2);
list.addFirst(1);
console.log(String(list)); // "{ 1 -> 2 -> 3 -> null }"
console.log(Object.prototype.toString.call(list)); // "[object LinkedList]"
感谢@bergi 和@loganfsmyth,他们的回答指出了我原始代码中的错误并将我推向了正确的方向,这里是有效的解决方案并将生成器用作迭代器 -
class SLListNode {
constructor(item) {
this.item = item;
}
toString() {
return `${this.item}`;
}
}
class SinglyLinkedList {
constructor() {
this.length = 0;
}
addFirst(item) {
const newNode = new SLListNode(item);
newNode.next = this.head;
this.head = newNode;
this.length++;
}
*[Symbol.iterator]() {
let temp = this.head;
while (temp) {
yield temp.item;
temp = temp.next;
}
}
getLength() {
return this.length;
}
toString() {
let str = "";
for (const temp of this) {
str = `${str} -> ${temp}`;
}
return str;
}
}
const list = new SinglyLinkedList();
list.addFirst(3);
list.addFirst(2);
list.addFirst(1);
console.log(list.toString());
Please find the complete code example in action here.
我正在尝试将生成器用作迭代器并将其与 toString
中的 for..of
循环结合使用,但不知何故它不起作用。
这是我的(生成器)迭代器的样子 -
*[Symbol.iterator]() {
let temp = this.head;
while (temp) {
yield temp.item;
temp = temp.next;
}
}
然后我尝试在 toString
方法中使用它,如下所示 -
[Symbol.toStringTag]() {
for (const temp of this) {
return `${temp} -> `;
}
}
我想象使用 for..of
循环和 this
引用应该调用迭代器,但它没有。这可以通过控制台日志中缺少 Iterator called
语句来观察,并且使用默认 toString
打印对象。
有什么我遗漏的吗?
你有几个大问题
Symbol.toStringTag
应该是解析为字符串而不是函数的 属性。这意味着[Symbol.toStringTag]() {
应该是
get [Symbol.toStringTag]() {
因此 属性 是一个 getter,它将 return 一个访问字符串。
console.log(list)
不调用.toString()
,所以需要console.log(list.toString())
.您会注意到,
list.toString() === "[object 1 -> ]"
,也可能不是您想要的。toStringTag
被附加到另一个字符串中,有点像`[object ${this[Symbol.toStringTag]}]`
所以如果你真的想要一个漂亮的字符串输出,你可能只想要
toString() {
作为您的方法,跳过
toStringTag
.如果你试图序列化整个列表,你的循环就没有意义,因为你
return
是列表中的第一个项目,而从不费心处理其余的的项目。
所以最后,我可能会把你想做的写成
toString() {
let result = "";
for (let item = this.head; item; item = item.next) {
if (result) result += ' -> ';
result += item.item;
}
return result;
}
I would imagine that using
for..of
loop with this reference should call the iterator but it doesn't.
确实如此。您只是从未在示例中调用该方法。
the object is printed to console using default
toString
instead
它不是,它是使用控制台自己的对象表示打印的(在 babeljs.io repl 上,它似乎是 .constructor.name
和 JSON.stringify
的混合)。
…
toString
method as shown below -[Symbol.toStringTag]() { …
没有。 Symbol.toStringTag
在被 Object.prototype
继承时用作标准 toString
表示的一部分。它不是一种方法,而是一个普通值(您可以使用 getter,但您不应该使用)。
如果要实现自定义 toString
方法,实际实现 that.
这是一个更新的示例,可以满足您的需求:
class SLListNode {
constructor(item, next) {
this.item = item;
this.next = next;
}
toString() {
return `${this.item} -> ${this.next}`;
}
}
class SinglyLinkedList {
constructor() {
this.length = 0;
this.head = null;
}
addFirst(item) {
this.head = new SLListNode(item, this.head);
this.length++;
}
*[Symbol.iterator]() {
console.log('Iterator called');
let temp = this.head;
while (temp) {
yield temp.item;
temp = temp.next;
}
}
getLength() {
return this.length;
}
toString() {
return `{ ${this.head.toString()} }`;
}
}
SinglyLinkedList.prototype[Symbol.toStringTag] = "LinkedList";
const list = new SinglyLinkedList();
list.addFirst(3);
list.addFirst(2);
list.addFirst(1);
console.log(String(list)); // "{ 1 -> 2 -> 3 -> null }"
console.log(Object.prototype.toString.call(list)); // "[object LinkedList]"
感谢@bergi 和@loganfsmyth,他们的回答指出了我原始代码中的错误并将我推向了正确的方向,这里是有效的解决方案并将生成器用作迭代器 -
class SLListNode {
constructor(item) {
this.item = item;
}
toString() {
return `${this.item}`;
}
}
class SinglyLinkedList {
constructor() {
this.length = 0;
}
addFirst(item) {
const newNode = new SLListNode(item);
newNode.next = this.head;
this.head = newNode;
this.length++;
}
*[Symbol.iterator]() {
let temp = this.head;
while (temp) {
yield temp.item;
temp = temp.next;
}
}
getLength() {
return this.length;
}
toString() {
let str = "";
for (const temp of this) {
str = `${str} -> ${temp}`;
}
return str;
}
}
const list = new SinglyLinkedList();
list.addFirst(3);
list.addFirst(2);
list.addFirst(1);
console.log(list.toString());