在Typescript/JavaScript中名称空间有一些客观的负面现象

问题描述:

我在互联网的不同文章中看到很多,并且听到很多名称空间都是古老而邪恶的东西。我听说很多你应该使用带有模块加载器而不是命名空间的模块,但我不明白使用它们有什么客观的好处。我已经阅读了关于命名空间的不同论点,但他们似乎对我并不那么有说服力。我将列出一些参数,你们请尝试用一些真实世界的例子来解释为什么它们是有效的:在Typescript/JavaScript中名称空间有一些客观的负面现象

  • 命名空间创建至少1个全局变量。但那有什么问题?我不在乎是否有一个叫做angular的全局变量。它会造成什么危害?
  • 对于模块,消费者决定要为导入的变量命名。命名导入的能力真的给了我什么?有多大可能会有2个变量命名为angular?而在这些少数情况下会出现重复的变量名我们不能仅仅做到这一点(我没有测试过这一点,但它应该在理论工作):

    var someOtherName = angular; 
    
    var angular = function() { 
    }; 
    
  • 模块与模块装载机使捆绑更容易因为他们把脚本按正确的顺序排列。但为什么他们不这样做,当你明确地告诉他们的顺序,通过在每个文件的顶部添加导入?同样,当你在tsconfig.json中使用“outFile”选项将三斜杠引用放在文件的顶部时,Typescript会按照正确的顺序构建JavaScript。这与进口有什么不同?

  • 模块装载机提高了性能。这个让我很困惑。假设我使用Typescript或.NET框架的捆绑工具生成了一个巨大的JavaScript文件,性能会不会相同,因为在这两种情况下我们都有1个文件? SystemJS会根据需要动态加载这些脚本。这个更有意义,但如果我最终得到一个25kb的JavaScript文件,如果按需加载每个kb,我会获得多少性能提升?毕竟,它只有25kb。

  • 即使假设模块和模块加载器比绑定到一个文件中并引用它在html中更好,如果我使用模块加载器来构建库,是否意味着使用我的库的任何人都需要安装加载器依赖项太?

在此先感谢您。

+0

欢迎来到Stack Overflow!请[参观],环顾四周,并通读[帮助],尤其是[*我如何提出一个好问题?](/帮助/如何问),[*什么类型的(/ help/dont-ask)和[*我可以在这里询问什么主题?*(/ help/on-topic)关闭原因:*“许多好问题都会产生某种程度的问题基于专家经验的意见,但对这个问题的回答往往几乎完全基于意见,而不是事实,参考或具体专业知识。“*和/或过于宽泛(询问**一个问题/问题)。 –

现在使用命名空间在JavaScript中被认为是一个坏主意有很多原因。 所有这些原因适用于TypeScript,因为它只是JavaScript的超集。

你自己回答了其中的一些,但可能看不到它们的意义。 我会尽力解决他们的问题。

隐依赖顺序

当您的代码使用通过命名一些库, 隐含地创建你的代码,您使用的库之间的依赖关系。

这意味着您必须自己管理依赖关系,以便正确加载它们, 或者您需要指示编译器/打包程序,以便它们可以正确安排加载顺序。

这意味着您有一个带外位置来管理此信息,并且容易出错。 如果明天你停止使用这个库,该怎么办?你会记得排除它吗? 让你的工具去完成工作要好得多。

命名空间冲突

这是一个常见的原因使用全局命名空间的人反对。 您可能认为这种情况很少发生,但一个例子是lodash vs underscore

命名空间版本

这是命名空间冲突的另一种形式。 如果您的代码和其中一个库使用相同的库x,但版本不同(x公开在全局名称空间x中),那么应在全局命名空间x中使用哪个版本?

模块解决了这个问题。 (免责声明:目前TypeScript类型系统不能正确处理多个版本,所以你可能会看到一些问题并需要解决它)。

禁止树摇动

随着ESM,捆绑诸如rollupwebpack可以执行树形晃动。 通过命名空间使用库不会给捆绑器分析您的代码和树形结构 - 摆脱不需要的位的信息。

刚性

当您通过命名空间暴露你的图书馆,图书馆的内部结构暴露,这意味着你不能没有营造出破改变你的消费重构你的代码。

是的,你可以通过小心地创建适配器或别名来避免这种情况,但这会让你的代码更难以维护,并且很可能最终陷入混乱。

安全

这是值得商榷的,但让你的代码在全局命名空间访问意味着你的代码和潜在的一些国家可以通过其他代码容易访问和修改。

我确信还有很多其他原因,但这些是我现在可以想到的。

+0

我很感谢你的回答,但你列出了那些理论上可能导致问题的东西。例如,我不认为我会同时使用lodash和下划线,或者使用不同版本的相同库。即便如此,这些类型的问题也可能存在于其他许多语言中,例如C#,但我们一直在用其他方式处理这些问题,并且不鼓励C#中的命名空间。 – User555

+0

这些问题不仅适用于您的应用程序,也适用于图书馆。在模块加载器之前,JavaScript没有链接器和DLL的概念,它解决了其他语言(如C#)中的一些问题。在JavaScript中并非如此。这是一种脚本语言。使用名称空间基本上是为了提高灵活性并使其非常有限。 – unional

+0

如果您使用2个具有相同名称空间和类名称的对象,则需要在C#中使用它们进行别名,但这是一种罕见的情况,我从来没有这样做过。你认为在这个问题中,我可能会出现像我在第2点中所做的那样“锯齿”这些对象的问题? – User555