2016-02-25 21 views
1

我真的很喜欢这样的NodeJS(和它的浏览器端的对应)处理模块:语言用的NodeJS/CommonJS的风格模块系统

var $ = require('jquery'); 

var config = require('./config.json'); 

module.exports = function(){}; 

module.exports = {...} 

我实际上是由ES2015 'import' spec这是非常相似,很失望大多数语言。

出于好奇,我决定去寻找它们实现甚至支持类似的导出/导入样式其他语言,但无济于事。

也许我失去了一些东西,或者更可能的是,我的谷歌foo是没有达到标准,但是这将是非常有趣的,看看哪些其他语言以类似的方式工作。

有没有人碰到类似的系统? 或者,也许有人甚至可以提供它不会经常使用的原因。

+0

您要查找的功能究竟是什么,区分这两个系统的功能是什么? – svick

+0

@svick主要是require函数,它返回一个函数或其他结构化数据。 与'从x导入x'隐式创建全局可访问属性相反,只能在文件顶部完成。 – ISNIT

回答

3

这是几乎不可能恰当地比较这些功能。人们只能比较它们在特定语言中的实现。我主要使用Java和nodejs语言收集了我的经验。

我发现这些差异:

  • 可以使用require不仅仅是为了使其他模块提供给您的模块的更多。例如,您可以使用它来解析JSON文件。
  • 您可以在代码中使用require无处不在,而import只能在文件的顶部。
  • require实际执行所需的模块(如果尚未执行),而import有着更为声明性特性。这对所有语言来说可能都不是这样,但这是一种趋势。
  • require可以从子目录加载私有依赖项,而import通常对所有代码使用一个全局名称空间。再说一遍,这也不是真的,而只是一种倾向。

责任

正如你所看到的,require方法有多重责任:声明模块依赖和读取数据。这更好地与导入方法分开,因为import应该只处理模块依赖关系。我猜想,您可以使用require方法读取JSON,它为程序员提供了一个非常简单的界面。我同意拥有这种简单的JSON阅读界面非常好,但是不需要将它与模块依赖关系机制混合使用。可以有另一种方法,例如readJson()。这将分离关注点,因此require方法仅用于声明模块依赖关系。

位置在代码

现在,我们只使用require为模块依赖关系,这是一个不好的做法,使用其他地方比在您的模块的顶部。当您在代码中的任何地方使用它时,都很难看到模块依赖关系。这就是为什么您只能在代码顶部使用import语句的原因。

我看不到导入创建全局变量的地步。它仅为每个依赖项创建一致的标识符,该标识符仅限于当前文件。正如我上面所说的,我建议只在文件的顶部使用require方法。它确实有助于提高代码的可读性。

它是如何工作

执行代码加载一个模块,也可以是一个问题的时候,尤其是在大项目。您可能会遇到一个循环,其中一个模块需要传递自己。这可能很难解决。据我所知,的NodeJS处理这种情况,像这样:当A需要B和B要求A和您的要求,然后开始:

  • 模块系统会记住它目前加载
  • 它执行代码在一个
  • 它会记住当前正在加载乙
  • 其B中执行代码
  • 它会尝试加载A,但A已经加载
  • 一个尚未完成加载
  • 它返回的一半装A到B
  • B不指望能在半载

这可能是一个问题。现在,人们可以争辩说,应该避免循环依赖,我同意这一点。但是,循环依赖只能在程序的不同组件之间避免。组件中的类通常具有循环依赖性。现在,模块系统可以用于两个抽象层:类和组件。这可能是一个问题。

接下来,require方法通常会导致单例模块,它们不能在同一个程序中多次使用,因为它们存储全局状态。然而,这不是系统的错误,但程序员错误地错误地使用系统。不过,我的观察是,require方法误导了特别是新程序员这样做。

依赖管理

的依赖管理是底图不同的办法确实是一个有趣的问题。例如,Java在当前版本中仍然错过了正确的模块系统。再次,它宣布了下一个版本,但谁知道这是否会成为现实。目前,您只能使用OSGi获取模块,这远非易于使用。

下层nodejs的依赖管理非常强大。但是,这也不完美。例如,通过模块API公开的非私有依赖性(通常是一个问题)是通过模块API公开的依赖性。但是,这是依赖管理的常见问题,因此它不限于nodejs。

结论

我想两者都没有那么糟糕,因为每个成功使用。然而,在我看来,importrequire有一些客观优势,如责任分离。因此,import可以被限制在代码的顶部,这意味着只有一个地方可以搜索模块依赖关系。此外,import可能更适合编译语言,因为这些不需要执行代码来加载代码。