在js中使用类与创建独立函数相比有什么好处

时间:2019-11-22 20:56:56

标签: javascript

我做了很多全栈JS工作,在创建带有封装逻辑的文件时通常遵循以下方法:

export const SOME_KEY_TO_STATE = 'some-key';
export const ANOTHER_KEY_TO_STATE = 'another-key';

let moduleState = {};

export function modifyState(someArg) {
  // ... do some logic
  // ... perhaps derive some new value based off of logic
  const newValue = derivedNewValue;
  moduleState[someKey] = newValue;
}

export function getSomeState(aKey) {
  // ... do some sanity checking?
  const initialValue = moduleState[aKey];

  // ... calculate value based on some conditions?
  const finalValue = calculatedValue;
  return moduleState
}

我偶尔也使用过类,这些类实际上提供了相同的结构,除了模块状态作为实例变量位于类内部,对于那些导出的常量可能是静态变量:

export default class SomeThing {
  static SOME_KEY = '';

  state = {};

  modifyState(arg) { ... }
  getSomeState() { ... }
}

我的首选方法是第一种,主要是因为我可以仅导入代码其他部分所需的内容,而无需使整个对象浮动(以及它的状态和其他我可能不使用的方法-该说法正确还是我完全不赞成?)。另外,如果我想在上下文中引用函数,则可以随时执行import { * as someName } from myModule

但是我很好奇,使用类而不是我概述的第一种方法是否会带来好处?

3 个答案:

答案 0 :(得分:3)

let moduleState = {};

这是全局状态which is best to be avoided。虽然它可以很好地封装在模块中,但它是一个静态变量,本质上是一个单例-它在整个应用程序中仅存在一次,是在加载模块时创建的。

在某些情况下,这可能是适当的,但通常是don't use singletons

class解决方案的明显优势是,您可以在任意位置(例如测试)将其实例化多次。因此,请确保了解这种差异,然后选择适当的模式。

  

我喜欢第一个,主要是因为我可以只导入我在代码其他部分中需要的内容,而无需使整个对象浮动(以及它的状态和其他我可能不使用的方法)

这确实很不错。您始终在应用程序中漂浮着完整的模块对象,状态和功能,这并不意味着它们会被优化。当然,当您不明确import时,它们就不在您的范围之内,但是拥有一个class实例也不会真的造成伤害。如果您不调用其所有方法,就像没有从模块中导入所有函数一样。

在调用普通函数或在对象上调用方法之间的语法差异实际上是次要细节,不应影响您的决定。您始终可以通过命名空间导入模块或销毁对象来回避它。

答案 1 :(得分:1)

这有待讨论,但我认为没有任何好处。这个问题已经在其他开发人员中讨论了很多,并归结为个人喜好。

类的主要原因是允许主要与其他语言一起工作的开发人员更轻松地跳转到JS。

正如Quora上的一位开发人员所说:

使用函数,工厂函数,老式JS类或ES6类将实现相同的功能,并且对浏览器级优化有所称赞,其中许多选项在由引擎运行时编译成相同的代码。< / p>

Here's a link to his answer.

另一件事是,OOP是设计的一种表达,它与结构有关。

许多现代JS框架(例如Angular,React或Vue)都非常重视结构良好的代码。 ReactJS甚至有class个组件,其中包含一个constructor,这又引发了编写更多OOP JS的想法。

在开发NodeJS应用程序时,甚至你们都在谈论使用类,这归结为个人语法偏好,因为V8为您完成了很多繁重的工作。 JS中的类只是对象周围的语法糖衣(几乎所有内容都在JS中),而V8引擎会为您翻译这些对象。

以下是有关该主题的一些好读物:

  1. Should we use classes in JS
  2. How JS works inside the V8 engine.

我希望能有所帮助。

答案 2 :(得分:1)

以下内容并不直接适用于我的问题,因为我的具体示例具有带有副作用的松散函数(也就是,它们会改变状态对象)。在这种情况下,即使函数是命名/松散函数而不是类,也不会发生 treeshaking。


使用第一种方法(松散函数)比第二种方法(类/对象)有一个优势,那就是如果您使用 webpack 和 treeshaking。

使用第二种方法(类/对象),webpack 不能对类的任何部分进行 treeshake,因此整个内容都被导入(因此具有 5 或 10 个方法的类将完全导入其所有 5-10 个方法).

另一方面,只要你只导入你需要的东西,松散的函数就可以被摇树。所以如果你只导入你需要的部分,一个有 5 - 10 个函数的文件将不会被完全导入:

import { only, what, iNeed } from 'module';

对于更多上下文,显然还有更多内容:https://webpack.js.org/guides/tree-shaking/