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

Javascript 与传统名称空间相比,ES6导出/导入用例,javascript,ecmascript-6,Javascript,Ecmascript 6,我不明白为什么以及在什么样的情况下会用到这个 我当前的web设置由许多组件组成,这些组件只是函数或工厂函数,每个都在它们自己的文件中,每个函数“骑”在应用程序名称空间中,比如:app.component.breadcrumbs=function(){…等等 然后GULP将所有文件合并在一起,我得到一个文件,这样页面控制器(每个“页面”都有一个控制器,用于加载页面所需的组件)就可以加载它的组件,比如:app.component.breadcrumbs(data) 所有组件都可以按需轻松访问,单个j

我不明白为什么以及在什么样的情况下会用到这个

我当前的web设置由许多组件组成,这些组件只是函数或工厂函数,每个都在它们自己的文件中,每个函数“骑”在应用程序名称空间中,比如:
app.component.breadcrumbs=function(){…
等等

然后GULP将所有文件合并在一起,我得到一个文件,这样页面控制器(每个“页面”都有一个控制器,用于加载页面所需的组件)就可以加载它的组件,比如:
app.component.breadcrumbs(data)

所有组件都可以按需轻松访问,单个javascript文件缓存良好。这种工作方式似乎非常好,从未发现这种工作方式有任何问题。当然,这种方式可以(而且是)很好地扩展

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

导入函数而不是仅仅将它们附加到应用程序的名称空间有什么意义?将它们“附加”更有意义

文件结构 然后在
homepage.js
中,它可以如下所示:
这是一个极其简化的代码示例,但您可以理解这一点。

对此的回答可能有点主观,但我会尽我所能

归根结底,这两种方法都支持为一项功能创建名称空间,这样它就不会与其他内容冲突。这两种方法都可以工作,但在我看来,模块、ES6或任何其他方法都提供了一些额外的好处

显式依赖 您的示例似乎非常倾向于“加载所有内容”的方法,但您通常会发现这是不常见的。如果您的
组件/header.js
需要使用
组件/breadcrumbs.js
,则必须做出假设。该文件是否已绑定到整个js文件中?您无法知道。您有两个选择:

  • 装载一切
  • 在某个地方维护一个文件,明确列出需要加载的内容
  • 第一个选项很简单,短期内可能还可以。第二个选项在可维护性方面很复杂,因为它将作为一个外部列表进行维护,很容易停止需要一个组件文件,但忘记删除它

    这还意味着您实际上是在为依赖项定义自己的语法,而现在在语言/社区中已经定义了一种语法

    如果你想开始将应用程序拆分为多个部分,会发生什么情况?假设你有一个应用程序,它是一个单独的大文件,在你的站点上驱动5个页面,因为它们一开始很简单,但不够大。现在,应用程序已经成长,每个页面应该有一个单独的JS文件。你现在已经失去了abili您必须使用选项#1,一些可怜的灵魂需要为每个结束文件构建这个新的依赖项列表

    如果你开始在一个新的地方使用一个文件呢?你怎么知道哪些JS目标文件真正需要它?如果你有二十个目标文件呢

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

    通过模块,您可以100%确定在何处使用自动化工具。您只需打包实际使用的文件

    订购 与依赖项列表相关的是依赖项排序。如果您的库需要为
    header.js
    组件创建一个特殊的子类,则您不再仅从
    app.routes.homepage()访问
    app.component.header()
    ,它可能在DOMContentLoaded上运行。相反,您需要在初始应用程序执行期间访问它。简单的连接不能保证它已经运行。如果您按字母顺序连接,并且您的新东西是
    app.component.blueHeader()
    ,则它将失败

    这适用于您可能希望在执行时立即执行的任何操作。如果您有一个模块在页面运行时立即查看页面,或发送AJAX请求或其他操作,那么如果它依赖于某个库来执行该操作呢

    这是另一个关于#1(加载所有内容)的论点,因此您必须再次维护一个列表。该列表将再次成为一个自定义的东西,而不是一个标准化的系统

    你如何培训新员工使用你自己制作的定制产品

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

    范围界定 您的解决方案将所有内容都视为标准脚本文件。这很好,但这意味着您需要非常小心,不要通过将全局变量放置在文件的顶级作用域中而意外创建它们。这可以通过手动添加
    (function(){…})()来解决
    关于文件内容,但同样,这是您需要知道的另一件事,而不是让语言为您提供它

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

    如果您需要加载一个库的两个版本,该怎么办?如果库很大,则有明显的缺点,但在很多情况下,您仍然希望用大的库来换取非功能性的库。如果您依赖全局对象,则现在由该库来确保它还公开一个API,如jQuery的
    noConflict
    。如果它没有,该怎么办?您有吗你自己加吗

    鼓励更小的模块 这一点可能更具争议性,但我确实在自己的内心观察到了这一点
    /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
    
    app.routes.homepage = function(){
        "use strict";
        var DOM = { page : $('#page') };
    
        // append whatever components I want to this page
        DOM.page.append(
            app.component.header(),
            app.component.sidemenu(),
            app.component.breadcrumbs({a:1, b:2, c:3})
        )
    };