创建基于可迭代的方法替代 JavaScript 数组的 filter() 方法

Creating iterable-based alternative to the filter() method of JavaScript arrays

我是初学者,正在阅读书中的迭代器一章

JavaScript: The Definitive Guide

我无法理解下面示例中的 next() 方法,该书是关于创建基于可迭代的 JavaScript 数组的 filter() 方法的替代方法。

// Return an iterable object that filters the specified iterable,
// iterating only those elements for which the predicate returns true
function filter(iterable, predicate) {
    let iterator = iterable[Symbol.iterator]();
    return { // This object is both iterator and iterable
        [Symbol.iterator]() {
            return this;
        },
        next() {
            for(;;) {
                let v = iterator.next();
                if(v.done || predicate(v.value)) {
                    return v;
                }
            }
        }
    };
}

让我们用一个数组来测试这个函数。

let a = [1,2,3,4,5]
let iter = filter(a, x => x>3) // Call the function

// Lets check the returned object of iter.next() method
iter.next() // {value: 4, done: false}
iter.next() // {value: 5, done: false}
iter.next() // {value: undefined, done: true}

我对这里的 next() 方法一头雾水。请帮助我理解它。

此外,我无法理解... next() 方法包含一个无限循环。但它打破了这个循环。这里没有这样的条件。

提前致谢

Also, I am not able to understand that... the next() method contains an infinite for loop. But what it makes it break that loop. There is no condition like that here.

return 打破循环。

I am completely confused about the next() method here. Please help me in understanding it.

这是它正在做的事情:

  1. 它调用 next 来获取下一个结果对象,它存储在 v 中。
  2. 如果 v.done 为真,则 returns v(打破循环)。这意味着迭代器已到达其序列的末尾。
  3. 如果v.done为假,则调用predicate传入v.value;如果 predicate returns 是真值,next returns v (打破循环)。

因此结果是由 filter 函数编辑的迭代器 return 将迭代谓词 return 为真值的值,并将 return结果对象 done 到达输入可交互的末尾时设置为真值。


我还没有读过这本书的最新版本(大约 15 年前我买了我的书),但我猜给定的代码是为了展示你将如何显式地使用迭代器,以及后来的 Flanagan将介绍 for-of 和生成器函数,它们提供了一种更简单的方法 filter:

function* filter(iterable, predicate) {
    for (const element of iterable) {
        if (predicate(element)) {
            yield element;
        }
    }
}

实例:

function* filter(iterable, predicate) {
    for (const element of iterable) {
        if (predicate(element)) {
            yield element;
        }
    }
}

let a = [1,2,3,4,5];
let iter = filter(a, x => x>3); // Call the function

// Lets check the returned object of iter.next() method
console.log(iter.next()); // {value: 4, done: false}
console.log(iter.next()); // {value: 5, done: false}
console.log(iter.next()); // {value: undefined, done: true}

我在最近出版的书 JavaScript: The New Toys 的第 6 章中在隐式(for-of、生成器)和显式之间来回切换。我发现将它们交织在一起是我能做的最好的事情,以帮助理解概念和细节。