与传统的命名空间相比,ES6导出/导入用例

时间:2015-10-10 20:00:15

标签: javascript ecmascript-6

我不明白为什么以及在什么情况下会使用它。

我当前的网页设置包含许多组件,这些组件只是函数或工厂函数,每个组件都在自己的文件中,每个函数都“骑”到应用程序命名空间,如:app.component.breadcrumbs = function(){...等等。

然后GULP只是组合了所有文件,最后我得到一个文件,所以页面控制器(每个“页面”都有一个加载页面所需组件的控制器)可以加载它的组件,如:{{ 1}}。

可以根据需要轻松访问所有组件,并且可以很好地缓存单个javascript文件以及所有内容。这种工作方式似乎非常好,从未看到这种工作方式有任何问题。当然,这可以(并且是)很好地缩放。

那么ES6如何为功能输入比我描述的更好?

导入函数的处理是什么,而不是仅将它们附加到App的命名空间?让他们“依恋”更有意义。

文件结构

app.component.breadcrumbs(data)

然后在/dist/app.js // web app namespace and so on /dist/components/breadcrumbs.js // some component /dist/components/header.js // some component /dist/components/sidemenu.js // some component /dist/pages/homepage.js // home page controller // GULP concat all above to /js/app.js // this file is what is downloaded 内,它看起来像这样:

homepage.js

这是一个极其简化的代码示例,但您明白了

1 个答案:

答案 0 :(得分:6)

对此的回答可能有点主观,但我会尽力而为。

在一天结束时,这两种方法都允许支持为一段功能创建命名空间,以便它不会与其他东西发生冲突。两者都有效,但在我看来,模块,ES6或任何其他模块都提供了一些额外的好处。

显式依赖

你的例子似乎非常偏向于“加载所有东西”#34;方法,但你通常会发现这种情况并不常见。如果您的components/header.js需要使用components/breadcrumbs.js,则必须进行假设。该文件是否已捆绑到整个JS文件中?你无从知晓。你有两个选择

  1. 加载所有内容
  2. 在某处明确列出需要加载的文件。
  3. 第一种选择很简单,在短期内可能还不错。第二个是可维护性很复杂,因为它将作为外部列表维护,很容易停止需要你的一个组件文件,但忘记删除它。

    这也意味着您实际上是在定义自己的依赖语法时,现在已经在语言/社区中定义了一个。

    当您想开始将应用程序拆分成碎片时会发生什么?假设您的应用程序是一个大型文件,可以在您的网站上运行5个页面,因为它们起初很简单并且不够重要。现在应用程序已经增长,应该每页提供一个单独的JS文件。你现在已经失去了使用选项#1的能力,而一些可怜的灵魂需要为每个结束文件构建这个新的依赖列表。

    如果您开始在新地方使用文件,该怎么办?你怎么知道哪些JS目标文件实际需要它?如果您有20个目标文件怎么办?

    如果您的整个公司都使用了一个组件库,并且其中一个组件开始依赖新的东西,该怎么办?如何将这些信息传播给使用这些信息的任何数量的开发人员?

    模块允许您100%确定使用自动化工具在何处使用。您只需要打包实际使用的文件。

    订购

    与依赖项列表相关的是依赖性排序。如果您的库需要创建header.js组件的特殊子类,则不再只是从app.component.header()访问app.routes.homepage(),这可能会在DOMContentLoaded上运行。相反,您需要在初始应用程序执行期间访问它。简单连接不能保证它将运行。如果你按字母顺序连接,而你的新事物是app.component.blueHeader()则会失败。

    这适用于您可能希望在执行时立即执行的任何操作。如果你有一个模块在运行时立即查看页面,或发送一个AJAX请求或任何东西,如果它依赖于一些库来做什么呢?

    这又是另一个参数#1(加载所有内容),因此您必须再次维护列表。该列表将再次成为您提出的自定义内容,而不是标准化系统。

    如何培训新员工使用您已构建的所有自定义内容?

    模块根据它们的依赖关系按顺序执行文件,因此您可以确定您所依赖的内容已经执行并且可用。

    作用域

    您的解决方案将所有内容视为标准脚本文件。这没关系,但这意味着你需要非常小心,不要通过将全局变量放在文件的顶级范围内而不小心创建全局变量。这可以通过在文件内容周围手动添加(function(){ ... })();来解决,但同样,您还需要知道一件事,而不是通过语言为您提供。

    冲突

    app.component.*是你所选择的,但没有什么特别之处,它是全球性的。如果你想从Github引入一个新的库,并且它也使用相同的名称怎么办?您是否重构整个应用程序以避免冲突?

    如果您需要加载两个版本的库,该怎么办?如果它很大,那么它有明显的缺点,但是在很多情况下,你仍然希望通过非功能性交易。如果您依赖于全局对象,那么现在由该库来确保它还公开了一个像jQuery的noConflict这样的API。如果它没有怎么办?你必须自己添加吗?

    鼓励更小的模块

    这个可能更有争议,但我确实在我自己的代码库中观察到它。使用模块,并且缺乏用它们编写模块化代码所需的样板文件,鼓励开发人员密切关注事物如何分组。最终制作" utils"文件是数千行的巨型函数,因为它更容易添加到现有文件中,而不是创建一个新文件。

    依赖网络

    具有明确的导入和导出使得很清楚什么取决于什么,这很好,但副作用是,更容易批判性地思考依赖关系。如果你有一个包含100个辅助函数的巨型文件,这意味着如果这些帮助程序中的任何一个需要依赖于来自另一个文件的东西,则需要加载它,即使此刻没有任何东西使用该辅助函数。这很容易导致大量不明确的依赖关系,并且意识到依赖关系是阻止这种情况的重要一步。

    标准化

    标准化还有很多要说的。 JavaScript社区已经朝着可重用模块的方向发展。这意味着,如果您希望进入一个新的代码库,那么您不需要通过弄清楚事物与彼此之间的关系来开始。你的第一步,至少从长远来看,不知道是什么东西是AMD,CommonJS,System.register或者是什么。通过在语言中使用语法,可以做出较少的决定。

    它的长短之处在于,模块为代码提供了一种标准的互操作方式,无论是您自己的代码还是第三方代码。

    您当前的流程是将所有内容连接到一个大文件中,只有在整个文件加载后才能执行,并且您可以100%控制正在执行的所有代码,然后您基本上定义了自己的模块规范基于您自己对特定代码库的假设。这完全没问题,没有人强迫你改变它。

    但是,对于JavaScript代码的一般情况,不能做出这样的假设。模块的目标恰恰是以不破坏现有代码的方式提供标准,而且还为社区提供前进的方法。模块提供的另一种方法是标准化的方法,并为您自己的代码和第三方代码之间的互操作性提供更清晰的路径。