除了隐藏在多范式/函数式语言(如 JavaScript)中的信息之外,闭包的真正价值主张是什么?

What is a closure's real value proposition besides information hiding in multi-paradigm / functional languages like JavaScript?

本文关键字:闭包 信息 是什么 范式 隐藏 函数 JavaScript 语言      更新时间:2023-09-26

当我第一次尝试理解闭包时,我遇到了一堵难以穿透的纸墙,上面写着难以理解的计算机科学,我必须先理解,然后才能触摸闭包。然后我了解到,在更多的猴子看,猴子做的基础上,虽然JavaScript关键字不允许Java的成语,(请原谅我在这里朦胧的记忆):

.JAVA:

class ObjectWithPrivateMember()
    {
    private int counter;
    public void ObjectWithPrivateMember()
        {
        counter = 0;
        }
    public void increment()
        {
        counter += 1;
        }
    public void decrement()
        {
        counter -= 1;
        }
    public void get_count()
        {
        return counter;
        }
    }

JavaScript(几年前的ECMAScript)没有真正的"私有"/"受保护"关键字,但是Java习语的自由翻译可能是这样的:

JAVASCRIPT:

var object_with_private_member = function()
    {
    var counter = 0;
    return {
        increment: function()
            {
            counter += 1;
            },
        decrement: function()
            {
            counter -= 1;
            },
        get_count: function()
            {
            return counter;
            }
        };
    }();

除了我立即反应"Ewwwww,胶带试图将JavaScript打扮成它不是的东西"之外,我在心理上把它归档为,"好吧,这就是如何用JavaScript的晦涩细节来硬塞Java习语。这可能很难直接了解 JavaScript 的伟大之处。

现在我回来回答"闭包到底有什么好处?"这个问题,维基百科条目提供了一些细节,并建议信息隐藏可能是一个主要用例,不仅仅是在具有重功能倾向的多范式语言中,而是对一流函数式语言的常见怀疑。当然,它更详细,提供了更多的细微差别,但它表明教科书"JavaScript对象与私有字段"用例并不像我想象的那么切线。

一个优秀的函数式程序员在纯函数式语言或具有函数式倾向的多范式语言中看到闭包的真实用例是什么?它们主要用于信息隐藏吗(维基百科文章提供了比上面的漫画更多的细微差别和细节,但至少乍一看,我的想法是闭包在 JavaScript 中可能比创建私有成员的后门方式更大、更有趣。

除了纯/多范式函数式语言中的信息隐藏机制之外,还有其他主要用例吗?

根据我的经验,隐私问题是一个次要的考虑因素,尤其是对于不可变的值。 如果他们无法改变它,你为什么关心谁看到它?

要理解闭包的价值,您首先必须了解一等函数的价值,然后很容易看出何时将某些数据与该函数相关联可能很方便。

考虑尝试从维基百科页面编写以下示例,而不使用闭包,但仍使用 filter 高阶函数:

// Return a list of all books with at least 'threshold' copies sold.
function bestSellingBooks(threshold) {
  return bookList.filter(
      function (book) { return book.sales >= threshold; }
    );
}

您需要找到一些其他方式将threshold传达给谓词函数。 在 OOP 中,您将创建某种对象,例如:

class ThresholdFilter implements Filterable {
  private threshold;
  ThresholdFilter(threshold) {
    this.threshold = threshold;
  }
  bool filter(book) {
    return book.sales >= this.threshold;
  }
}
function bestSellingBooks(threshold) {
  return bookList.filter(new ThresholdFilter(threshold));
}

或者,您可以更改 filter 函数以接受某种私有通用数据结构进行存储和传递,这使得filter和谓词函数更加复杂和耦合。 关闭现在开始看起来很好,对吗?

更多情况下,闭包大大减少了耦合并简化了使用高阶函数的代码。 这是函数式程序更加简洁的主要原因。