2017-02-16 49 views
5

我有一个JavaScript链表,我需要使用for of循环进行迭代。我已经差不多完成了它,但似乎没有办法获得结果中包含的第一个值。这里是一个简化的版本:在ES6中建立一个可链接的列表

var obj = {value: 1, next: {value: 2, next: {value: 3, next: {value: 4, next: {value: 5, next: {value: 6, next: {value:7, next: null}}}}}}}; 

obj[Symbol.iterator] = function() { 
    var current = this; 
    return { 
    next() { 
     if (current.next !== null) { 
     current = current.next; 
     return {value: current.value, done: false}; 
     } 
     return {done: true} 
    } 
    } 
} 

for (const x of obj) { 
    console.log(x) 
} 

// this is how you get the values printed with no loop 
// console.log(obj.value + '->' + obj.next.value + '->' + obj.next.next.value) 

回答

4

的问题是你移动current到下一个节点检索value之前。

var obj = {value: 1, next: {value: 2, next: {value: 3, next: {value: 4, next: {value: 5, next: {value: 6, next: {value:7, next: null}}}}}}}; 
 

 
obj[Symbol.iterator] = function() { 
 
    var current = this; 
 
    return { 
 
    next() { 
 
     if (current) { 
 
     var value = current.value; 
 
     current = current.next; 
 
     return {value: value, done: false}; 
 
     } 
 
     return {done: true}; 
 
    } 
 
    }; 
 
}; 
 

 
for (const x of obj) { 
 
    console.log(x); 
 
}

实现了generator function迭代器要容易得多。

var obj = {value: 1, next: {value: 2, next: {value: 3, next: {value: 4, next: {value: 5, next: {value: 6, next: {value:7, next: null}}}}}}}; 
 

 
obj[Symbol.iterator] = function*() { 
 
    var current = this; 
 
    while (current) { 
 
    yield current.value; 
 
    current = current.next; 
 
    } 
 
}; 
 

 
for (const x of obj) { 
 
    console.log(x); 
 
}

1

您应该测试的current,不current.next

obj[Symbol.iterator] = function() { 
    var current = this; 
    return { 
    next() { 
     if (current !== null) { 
     var res = {value: current.value, done: false}; 
     current = current.next; 
     return res; 
     } else { 
     return {done: true}; 
     } 
    } 
    }; 
} 

,但可以把它写成一个发电机方法简单得多:

obj[Symbol.iterator] = function*() { 
    for (var current = this; current !== null; current = current.next) { 
    yield current.value; 
    } 
} 

顺便说一句,我w建议不要将此迭代器放在列表的每个节点上(甚至是第一个节点上)。放在一个单独的对象指向列表的头,或者使它成为一个静态辅助功能:

let list = { 
    head: obj, // could be null either 
    *[Symbol.iterator]() { 
    for (var current = this.head; current !== null; current = current.next) { 
     yield current.value; 
    } 
    } 
} 

function* linkedList(head) 
    for (; head !== null; head = head.next) { 
    yield head.value; 
    } 
}