【问题标题】:Creating iterable-based alternative to the filter() method of JavaScript arrays为 JavaScript 数组的 filter() 方法创建基于可迭代的替代方案
【发布时间】:2021-11-09 09:10:13
【问题描述】:

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

JavaScript:权威指南

我无法理解以下示例中的 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() 方法包含无限 for 循环。但它是什么让它打破了这个循环。这里没有这样的条件。

提前致谢

【问题讨论】:

    标签: javascript loops iterator


    【解决方案1】:

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

    return 打破循环。

    我对这里的 next() 方法完全感到困惑。请帮助我理解它。

    这是它的作用:

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

    所以结果是 filter 函数返回的迭代器将迭代谓词为其返回真值的值,并在到达末尾时返回一个将 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,生成器)和显式之间来回切换。我发现将它们交错是我能做的最好的事情,以帮助理解概念和细节。

    【讨论】:

    • 感谢您的清晰解释。对我的理解帮助很大。我很想读这本书并增加我的知识:)
    • 我只是想再问一个一般性问题。扩展运算符如何与返回的可迭代对象一起工作。例如[...filter(a, x => x>3)] 将返回[4, 5]。我的意思是.. 他们是如何在幕后工作的。
    • 他们是否继续调用该函数,如果返回v,它将v.value 存储在我的数组中。而且.. 它不断地调用它直到它到达v.value === undefineddone === true
    • @RakeshPoddar - 当您在数组文字 ([...something]) 中使用 spread 时,它会从 something 获取迭代器并重复调用它,将返回的值存储在新数组中,直到它看到done 标志。 (注意:... 不是运算符。运算符不能像展开和休息语法那样做。)
    • 非常感谢您为我解惑。我也有一些直觉,它必须以这种方式工作,但我的语言术语被你解得非常清楚。
    猜你喜欢
    • 2010-11-30
    • 2012-10-18
    • 2021-10-21
    • 2016-09-30
    • 2015-04-17
    • 2018-06-06
    • 2013-07-16
    • 2010-09-10
    • 1970-01-01
    相关资源
    最近更新 更多