如何理解JavaScript中的ES模块,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。
创新互联是一家集网站建设,印江企业网站建设,印江品牌网站建设,网站定制,印江网站建设报价,网络营销,网络优化,印江网站推广为一体的创新建站企业,帮助传统企业提升企业形象加强企业竞争力。可充分满足这一群体相比中小企业更为丰富、高端、多元的互联网需求。同时我们时刻保持专业、时尚、前沿,时刻以成就客户成长自我,坚持不断学习、思考、沉淀、净化自己,让我们为更多的企业打造出实用型网站。
模块在每个编程语言中都能找到。它是一种能在一个代码块中引入另一个代码的模块功能的方法。这些模块是开发人员开发的具有特定功能的代码,可以在项目其他地方重复使用。模块化为你提供了一些好处,比如代码的可复用性和模块化。
如果你之前一直在使用JavaScript开发代码,你就会知道早期的JavaScript没有这样的模块功能。开发者为了将js文件加载到他们的页面中,不得不使用HTML <script>标签。直到后来,几种模块定义规范才开始出现。
CommonJS — Node.js中使用的module.export和require语法
Asynchronous Module Definition (AMD)
Universal Module Definition (UMD)
ES Modules
首先,我们先来看下为什么需要这些模块化定义的规范
为什么我们需要模块化
每当你思考程序是如何工作的,其实它们所做的就是变量管理。它为变量赋值,修改变量,将两个变量组合在一起等等。但是当变量的数量随着你的应用程序的规模而增加时,你会发现你的代码管理起来会非常麻烦。
解决这个问题的方法是只需要考虑几个变量。JavaScript实现这一目标的方式被称为作用域。由于JavaScript中的作用域定义方式导致函数不能访问其他函数中定义的变量。虽然这使得你的变量不能被其他函数访问,但这又引起了另一个问题--你很难在不同函数之间共享变量。解决这个问题就是将它们定义在全局作用域上。
虽然这种方法可以解决问题,但并不推荐。你的脚本标签应该按照正确的顺序,你必须确保没有人改变这个顺序。如果顺序确实发生了变化,你的应用程序将抛出一个错误。这使得代码管理变得很棘手。你永远不知道什么会破坏什么。任何函数都可以访问,所以你不知道哪些函数依赖于哪些脚本。
另一个问题是,在该全局范围内的每一部分代码都可以被其它代码改变。这将允许恶意的和非恶意的代码访问甚至修改你的全局变量,无论是否有恶意。
所以需要引入模块来帮助克服这些问题。
模块化是如何优雅的解决这个问题的
模块可以让你更好地组织和管理变量和函数。通常情况下,属于同一功能的函数和变量会被放在一个模块中。这就把这些变量放到了模块作用域中。模块作用域可以用来在模块中的函数之间共享变量。
这也使得变量也可以为其他模块所用。他们可以明确的说哪些变量、类或函数应该对外部模块可用。这就是所谓的导出。一旦你有了一个导出,其他模块就可以明确地说它们依赖于该变量、类或函数。由于这种明确的关系,你将知道如果你删除一个模块,哪些模块将被破坏。
一旦你能够导入和导出变量和函数,你就可以更容易地将你的代码分割和分解成可以独立工作的代码块。你以后可以通过使用这些模块来构建你的应用程序,类似于用乐高积木来构建。
为了实现这个超级有用的功能,已经多次尝试用JavaScript添加模块功能。
现有的模块化系统
CommonJS
CommonJS是NodeJS一直在使用的。使用Node,你会得到CommonJS的module.exports和require并可以直接使用。但是,与Node不同的是,浏览器并不支持CommonJS。此外,CommonJS会同步加载模块,因此对于浏览器来说,它不是一个最佳的解决方案。你可以使用Webpack或Browserify等打包程序来解决这个问题。
// filename: bar.js // dependencies var $ = require('jquery'); // methods function myFunction(){}; // exposed public method (single) module.exports = myFunction;
Asynchronous Module Definition (AMD)
AMD诞生于一群不喜欢CommonJS发展方向的开发者。事实上,AMD在发展初期就从CommonJS中分裂出来了。AMD和CommonJS的主要区别在于AMD是异步加载模块的。这在浏览器中非常受欢迎,因为启动时间对于良好的用户体验至关重要。
// filename: bar.js define(['jquery'], function ($) { // methods function myFunction(){}; // exposed public methods return myFunction; });
由于CommonJS和AMD在各自的领域相当流行,所以需要一个 "通用 "的模式来支持两种风格。但事实证明,UMD又乱又丑。虽然它确实同时支持AMD和CommonJS,也支持老式的 "全局 "变量定义。
Universal Module Definition (UMD)
什么是ES模块
众所周知,JavaScript缺乏一个标准模块定义规范。因此,在ES6中提出了一个单一的、原生的模块标准。import和export指令允许程序在不运行代码的情况下导入导出,从而建立一个完整的模块依赖关系。
其语法格式还是简单好用的,并且兼容浏览器中的同步和异步操作模式。ES模块在浏览器中很快就可以使用,但在Node.js中,要想出一个向后兼容并能实现增量升级的解决方案就有点难了。在Node.js中,原生的ES模块在实验性模块标志后面长期可用。
下面以ES6模块为例。
JavaScript
//------ library.js ------ export const sqrt = Math.sqrt; export function square(x) { return x * x; } export function diagonal(x, y) { return sqrt(square(x) + square(y)); } //------ main.js ------ import { square, diagonal } from 'library'; console.log(square(13)); // 169 console.log(diagonal(12, 5)); // 13 const app = document.getElementById("app"); app.innerHTML = "<h2>Demo App for ES Modules</h2>"; const input = document.getElementById("num"); input.addEventListener("change",displaySquare); function displaySquare(){ var sqrOutput = document.getElementById("sqr"); sqrOutput.value = square(input.value); }
HTML
<HTML> <head> <title>ES Modules Demo</title> </head> <body> <script type="module" src="./main.js" ></script> <div id="app"></div> <label>Input</label> <input id="num" type="number" placeholder="Enter number here"/> <br> <label>Output</label> <input id="sqr" type="number" disabled style="margin- top:20px"/> </body> </HTML>
如上图所示,在HTML文件中,你需要在脚本标签中指定type="模块",浏览器才会将其视为ECMAScript模块。
兼容性
为了向后兼容,你可以在脚本标签中包含nomodule(其中加载的JS文件是单个打包文件)。支持ES模块的浏览器会知道忽略这一点。这个解决方案即使在最老的浏览器中也能使用。Willem的回答已经很好的解释了这个问题。
在上面的方案中,我们会在HTML中加入这样的内容。
<script type="module" src="./main.js" > </script> <script nomodule src="./fallback.js" > </script>
如果你是在本地测试,你将需要在服务器上运行这个,因为你会遇到CORS问题。请在这里阅读更多信息。模块以绝对或相对引用导入,必须以"/"、"./"或"./"开头。
注意:
动态导入
最新的ES2020版本确实带有动态导入功能。要动态导入模块,导入关键字可以作为函数调用。当以这种方式使用时,它会返回一个promise。
import('/modules/library.js') .then((module) => { // Do something with the module. }); //or using await let module = await import('/modules/library.js');
关于es模块的详细兼容性可以参考这里 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules#import以及https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules#export
您是否应该选择使用ES模块?
对于浏览器来说,ES模块是新的标准。可以开箱即用的异步模块加载功能,你可以获得更快的启动时间以更好的性能。虽然您可以在浏览器中使用CommonJS与一些额外的插件,但强烈建议您切换到ES模块,因为它们是浏览器中的原生模块。
ES原生模块允许您获得单个模块的加载,而不是单个打包文件。这是相当有用的,它减少了加载数据的大小。浏览器对原生模块的兼容性也很重要,因为它决定了原生的ES模块是否会被实现,或者我们是否会回退到我们的模式,它将加载一个单一的文件。当你得到一个单一的bundle文件时,其中一个问题是,当你的应用程序变得更大时,bundle js文件的大小也会增加,从而影响启动时间和性能。你可以通过使用代码拆分来避免这个问题,这是现代打包器(如webpack)中的一个功能。但在某些情况下,我们可能会选择模块打包器,如webpack而不是ES模块。如果你有CSS、图像、字体等资产,甚至是XML、CSV等数据文件,你可能会选择webpack解决方案,因为webpack提供了文件打包功能。
你还应该考虑到浏览器对HTTP2的支持。当你使用本地模块时,你的浏览器会单独加载这些模块。但在HTTP2的帮助下,我们可以用一个连接同时服务多个请求,而不是发送多个HTTP请求。根据CanIUse的数据,96.49%的浏览器使用HTTP2。
但是当你开发一个应用程序时,即使是剩下的3.51%也应该满足,那么你可能会想改用webpack。这是因为如果你坚持使用原生的ES模块,你的应用程序将需要发送几个HTTP请求来加载每个单独的模块。
在Node中,情况就完全不同了。由于该功能仍被标记为实验性的,所以你最好坚持使用CommonJS。不过你还是可以尝试一下ES模块。你可以在这里查看上面例子的源代码。你也可以在这里查看实时演示。
关于如何理解JavaScript中的ES模块问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注创新互联行业资讯频道了解更多相关知识。
当前文章:如何理解JavaScript中的ES模块
URL标题:https://www.cdcxhl.com/article6/jochog.html
成都网站建设公司_创新互联,为您提供做网站、定制网站、定制开发、电子商务、企业网站制作、动态网站
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联