什么是 JS 模块之间数据编组的好模式?

What is a good pattern for data marshaling between JS modules?

这个问题是关于在服务器上使用 JS 模块构建数据对象以供另一个模块使用的最佳实践。

我们有许多用于 Web 应用程序的模块,例如登录视图、表单处理程序,它们包含不同的数据片段,例如用户状态、应用程序状态等,我们需要将这些数据发送到需要特定的对象格式。我们应该在哪里映射数据? (选择我们要发送的内容,重命名键,删除不需要的值。)

  1. 在每个模块中。例如:登录知道分析及其格式 要求。
  2. 在分析模块中。现在分析必须知道 关于每个模块的源格式。
  3. 在单独的 [模块]-分析模块中。然后我们将有许多文件没有太多上下文需要调试和理解。

我的团队在什么是正确设计上存在分歧。我很好奇是否有关于这个问题的权威声音可以帮助我们解决这个问题。

提前致谢!

例如,

var objectForAnalytics = { 
  logged_in: user.get('isLoggedIn'), 
  app_context: application.get('environment') 
}; 
analytics.send(objectForAnalytics);

这个简短的示例脚本使用了 3 个模块中的函数。它应该存在于组织良好的应用程序中的什么位置?

JS 不做传统意义上的编组。

由于该语言鼓励 duck typing 并在单个 VM 中运行所有加载的模块,因此每个模块都可以简单地传递数据并让消费者选择他们感兴趣的字段。

从历史上看,编组有两个主要目的:

  1. 向另一个模块提供它期望的数据,因为 C 风格的结构和对象不支持额外的数据(通常)。
  2. 在基于两个编译器构建的两种语言或模块之间传输数据,这两种编译器可能使用不同的内存布局、调用约定或 ABI。

JavaScript 使用 JSON 解决了第二个问题,但第一个问题本质上是用字典式对象解决的。传递具有 1000 个键的对象与传递具有 2 个键的对象一样快,因此您可以(并且经常被鼓励)简单地向消费者提供您所拥有的,并让他们决定他们需要什么。

这在 Typescript 等语言中得到了进一步加强,其中参数类型的约定只是一组最小的要求。 TS 允许您传递超出这些要求的对象(通过具有其他字段),而不是仅验证您是否了解消费者在合同中声明的内容并已满足该要求。

当您确实需要转换一个对象时,可能是因为两个库使用相同的数据但键不同,创建一个具有浅引用的新对象非常容易:

let foo = {
  bar: old.baz,
  baz: old.bin
};

这不会更改或复制基础数据,因此对原始数据(或副本)的任何更改都会传播到另一个数据。这不包括原始值,它们是不可变的,因此不会传播。