现代 Javascript 中的闭包 VS 类

Closures VS Classes in modern Javascript

对于主要目标是创建另一个函数的闭包,我想知道在现代 javascript 中是否最好只在现代 javascript 中使用 类。

// Closure way private counter
const countPlusOne = () => {
    let count = 0;
    return () =>{
        count++;
        console.log(count);
    }
}
let demoAdd = countPlusOne();
demoAdd(); // 1
demoAdd(); // 2
demoAdd(); // 3

老实说,我从来不喜欢以这种方式使用闭包(但我认为它们非常适合中间件之类的东西),因为它们很难阅读。

那么,我是否应该像上面那个那样重构闭包到 类?它们的行为似乎更类似于其他语言中的典型对象。

// Class way private counter
class countPlusClass{
    count = 0;
    add(){
        this.count++;
        console.log(this.count)
    }
}
const demo = new countPlusClass();
demo.add(); // 1
demo.add(); // 2
demo.add(); // 3

类 并不总是更好。这真的取决于情况。每个在您的编程工具集中都有自己的位置。

一个class具有以下优点:

  1. 语言中有定义的语法
  2. 您可以 sub-class 一个 class 来扩展它
  3. 您可以更轻松地拥有许多属性和许多方法。
  4. 方法在严格模式下自动 non-enumerable 和 运行。
  5. 使用 class 的代码中的语法有点 self-describes 自 new countPlusClass() 以来发生的事情清楚地表明您正在创建一个对象,该对象随后将具有方法和可能的状态.这在您显示的闭包中并不明显。
  6. 对于具有很多方法的对象,class 使用的原型有一些 space-savings 好处。
  7. 开发人员工具将识别 class 的实例并知道如何显示它,auto-complete 在为它键入代码时,如何在调试器中表示它,如何在错误中使用它消息等...

闭包具有以下优点:

  1. 闭包中的数据是完全私有的。没有人可以从关闭外到达它。
  2. 在某些情况下,调用者可能会发现使用闭包需要更少的代码,因为您进行一次函数调用(有时传递参数),然后返回另一个函数,该函数然后实现它应该做的一件事(我想到了你提到的中间件)。

所以,我想说的是,如果您想要或需要或重视 class 的任何好处,请使用 class。

如果您不想要或不需要 class 的任何好处并且闭包的更简单的界面可以满足您的需求,或者如果您确实需要闭包的隐私,那么您可以选择关闭。

我想说的是,对于给定的情况,其中一种工具可能更“适合”手头的问题。


正如评论中所提到的,您还可以拥有可以是闭包的工厂函数(在闭包中保留私有状态),并且可以 return 具有方法 and/or 属性的对象可以甚至是通过实例化 class 创建的对象。因此,这些概念也可以全部结合起来,以获得两者的一些好处。

闭包比您想象的 class 有显着优势:使用 class,如果您像您一样使用 public class 字段任何 访问实例的代码都可以修改它的值。这通常是不可取的 - scope should generally be constrained as possible 并且您不希望 class 的正确性取决于 class 的消费者不修改它(无论是无意还是故意)。

class countPlusClass{
    count = 0;
    add(){
        this.count++;
        console.log(this.count)
    }
}
const demo = new countPlusClass();
demo.add(); // 1
demo.add(); // 2


// some code elsewhere in the codebase that has access to the demo instance:
demo.count = 55555;


demo.add(); // not 3...

相比之下,闭包是完全私有的 (barring strange, exceptional circumstances)。

如果您要使用 class,并且想模拟闭包的隐私,请确保改用私有 class 字段,这样就无法在 class.

class countPlusClass{
    #count = 0;
    add(){
        this.#count++;
        console.log(this.#count)
    }
}
const demo = new countPlusClass();
demo.add(); // 1
demo.add(); // 2


// some code elsewhere in the codebase that has access to the demo instance
// cannot modify the private field
demo.count = 55555;


demo.add(); // not 3...

至于closure-based对象还是class哪个更好?这取决于每个开发人员。

不,class并不总是更好。他们只是不同。我想说的主要区别是

  • constructor/factory函数返回的thing的接口。 class 实例具有属性和方法,通常有多个,而闭包只是一个您可以调用的函数 - 具有单一功能。调用它们的语法不同,额外的方法名称有时是多余的,有时是有益的。
  • 在 OOP 中,对象应该具有标识和状态。在 FP 中,函数应该是纯函数。当然,您不需要遵循特定的范例,无状态对象和不纯函数一样都很好(尽管那时可能称它们为“过程”),但在争论可读性和可维护性时请记住这些约定。

所以请明智地选择。您(可能在将来)需要多种方法吗?你封装状态吗?然后使用 class 创建对象。你只需要一个函数来调用吗?然后创建一个闭包。