gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-03 09:55:17 24 4
gpt4 key购买 nike

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

我当前的 Web 设置由许多组件组成,它们只是函数或工厂函数,每个都在自己的文件中,并且每个函数都“驾驭”应用程序命名空间,例如:app.component.breadcrumbs = function(){...等等。

然后 GULP 只是组合所有文件,我最终得到一个文件,因此页面 Controller (每个“页面”都有一个加载页面所需组件的 Controller )可以只加载它的组件,例如:app.component.breadcrumbs(data) .

所有组件都可以按需轻松访问,并且单个 javascript 文件得到了很好的缓存。这种工作方式看起来非常好,从来没有发现这种工作方式有任何问题。当然,这可以(并且正在)很好地扩展。

那么 ES6 的函数导入如何比我描述的更好?

导入函数而不是将它们附加到应用程序的命名空间有什么关系?让他们“依附”更有意义。

文件结构

/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它看起来像这样:
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})
)
};

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

最佳答案

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

归根结底,这两种方法都支持为某项功能创建命名空间,这样它就不会与其他事物发生冲突。两者都有效,但在我看来,模块、ES6 或任何其他模块提供了一些额外的好处。

显式依赖

您的示例似乎非常倾向于“加载所有内容”方法,但您通常会发现这种情况并不常见。如果您的 components/header.js需要使用components/breadcrumbs.js ,必须做出假设。该文件是否已捆绑到整个 JS 文件中?你没有办法知道。你有两个选择是

  • 加载所有内容
  • 在某处维护一个文件,明确列出需要加载的内容。

  • 第一种选择很容易,短期内可能没问题。第二个对于可维护性来说很复杂,因为它将作为外部列表进行维护,很容易停止需要您的组件文件之一但忘记删除它。

    这也意味着您实际上是在为依赖项定义自己的语法,而现在又在语言/社区中定义了语法。

    当您想开始将应用程序拆分为多个部分时会发生什么?假设您有一个应用程序,它是一个单独的大文件,可以驱动您网站上的 5 个页面,因为它们开始时很简单,而且还不够大。现在应用程序已经增长,应该为每页提供一个单独的 JS 文件。您现在已经失去了使用选项 #1 的能力,有些可怜的人需要为每个最终文件构建这个新的依赖项列表。

    如果您开始在新位置使用文件怎么办?你怎么知道哪些JS目标文件实际上需要它?如果您有二十个目标文件怎么办?

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

    模块使您可以通过自动化工具 100% 确定地知道在何处使用了什么。您只需要打包您实际使用的文件。

    订购

    与依赖项列表相关的是依赖项排序。如果您的图书馆需要为您的 header.js 创建一个特殊的子类组件,您不再只是访问 app.component.header()来自 app.routes.homepage() ,这可能会在 DOMContentLoaded 上运行。相反,您需要在初始应用程序执行期间访问它。简单串联不保证它会运行。如果您按字母顺序连接并且您的新事物是 app.component.blueHeader()那么它就会失败。

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

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

    您如何培训新员工使用您构建的所有这些自定义东西?

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

    范围界定

    您的解决方案将所有内容都视为标准脚本文件。这很好,但这意味着您需要非常小心,以免意外地将全局变量放置在文件的顶级范围内。这可以通过手动添加 (function(){ ... })(); 来解决围绕文件内容,但同样,这是您需要知道的另一件事,而不是由语言为您提供。

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

    如果需要加载一个库的两个版本怎么办?如果它很大,这有明显的缺点,但是在很多情况下,您仍然希望用大笔交易来换取非功能性。如果你依赖一个全局对象,那么现在由该库来确保它也暴露了一个 API,比如 jQuery 的 noConflict .如果没有呢?必须自己添加吗?

    鼓励更小的模块

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

    依赖网络

    具有明确的导入和导出可以非常清楚什么取决于什么,这很好,但它的副作用是更容易批判性地思考依赖关系。如果您有一个包含 100 个辅助函数的巨型文件,这意味着如果这些辅助函数中的任何一个需要依赖另一个文件中的某些内容,则需要加载它,即使此时没有任何人使用该辅助函数。这很容易导致大量不明确的依赖关系,而意识到依赖关系是阻止这种情况的一大步。

    标准化

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

    总而言之,模块为代码提供了一种标准的互操作方式,无论是您自己的代码还是第三方代码。

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

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

    关于javascript - 与传统命名空间相比,ES6 导出/导入用例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33058403/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com