javascript的基本语法遵循的标准是,io模块的作用是什么
JS 模块化流程在JS 技术的不断发展中,一路上遇到了诸如模块化等各种问题。
那么什么是模块化以及它的目的是什么?
定义:如何将一段代码封装成一个有用的单元,以及如何注册这个模块的功能和输出值依赖引用:如何引用其他代码单元。
到目前为止,大致分为以下几个里程碑阶段:
原始开发方式--- CommonJS --- AMD --- CMD --- UMD --- ES6Module 原始开发方式最初,JS 本身并没有模块机制。该项目有多个js文件。
//a.jsfunction foo() {}//b.jsfunction bar() {}//c.jsfoo()HTML 加载
使用传统的开发方式,随着项目变得越来越复杂,需要读取的代码量和文件量也会随之增加。但是,需要考虑以下几点。
命名问题:所有文件都是全局挂载的,污染了全局环境,所以必须考虑命名冲突。依赖性问题:脚本是按顺序加载的。如果文件之间存在依赖关系,则必须考虑.js 文件的加载顺序。互联网故障。文件太多会增加所需的请求数量并增加加载时间。 CommonJS node.js CommonJS规范主要在服务器端运行,同步加载模块,但加载的大部分文件资源都在本地服务器上,因此不存在执行速度或执行时间的问题。 Node.js 很好地实现了这个规范。规范规定单个文件是一个模块。模块函数有几个主要命令:require 和module.exports。 require命令用于输入其他模块提供的功能。 module.exports命令用于标准化模块的外部接口。输出是值的副本。一旦输出就无法修改并被缓存。
//moduleA.jsvar name='Drex'function foo() {}module.exports=Exports={ name, foo}//moduleB.jsvar ma=require('./moduleA') //后缀.jsexports 就是It如下。 bar=function() { ma.name==='Drex' //true ma.foo() //运行foo方法}//moduleC.jsvar mb=require('./moduleB')mb.bar(例如,可以看到require(moduleId) 是用来加载其他模块的内容的,它的返回值是引用外部模块暴露的API,然后module.exports 或者exportsoutputs 用来为当前模块的方法提供接口和变量。
最后,模块通过节点执行。
AMD Require.js AMD(Asynchronous Module Definition - 异步加载模块定义)规范规定了定义模块的规则,其中单个文件就是一个模块,模块及其依赖项可以异步加载。它主要工作在浏览器端,因此适合浏览器的异步加载模块环境,不影响后续语句的执行。该规范在RequireJs 推送期间逐渐完善。
模块函数有几个主要命令:define、require、return 和define.amd。 Define是一个全局函数,define(id, dependency, Factory),用于定义模块。 require命令用于输入其他模块提供的功能。返回命令用于规范模块的外部接口。 Define.amd 属性是一个对象。该属性的存在表明该函数遵循AMD 规范。
//moduleA.jsdefine(['jQuery','lodash'], function($, _) { var name='Drex', function foo() {} return { name, foo }})//index.jsrequire( ['moduleA'], function(a) {a.name==='Drex' //truea.foo() //在模块A 中运行函数foo //sth.}) //Index.html here Here我们使用define定义模块,返回打印界面,require加载模块,这是AMD官方推荐的用法。当然,也可以使用其他兼容的编写方式,比如支持Simplified CommonJS Wrapper 格式,但背后仍然保留了原始的AMD 工作逻辑。 AMD的工作逻辑是预加载、预运行。使用Requirejs,当你声明一个依赖模块时,模块中的代码会立即加载并执行,从而允许后续的回调函数在所需的环境中运行。为了更好地优化请求,还推出了打包工具r.js,以减少需要加载的文件数量。使用r.js开发require.js模块并打包示例
CMD Sea.js CMD(Common Module Definition)规范主要是在Sea.js 的推广过程中创建的,其中文件就是模块,模块代码可以像Node.js 一样编写。它主要运行在浏览器中,但也可以在Node.js 中运行。
//moduleA.js//定义模块Define(function(require,exports, module) { var func=function() { var a=require('./a') //然后才module a.func () if (false) { var b=require('./b') //只有这样b 模块才会被加载b.func() } } //运行sth.exports.func=func;} )//index .js//Module seajs.use('moduleA.js', function(ma) {var ma=math.func()})//要加载HTML ,您需要将sea.js 文件引入到您的页面中。这里,define是一个全局函数,用于定义模块,并通过exports向外界提供接口。如果以后想使用该模块,可以通过require 检索它提供的接口。当你最终使用一个组件时,通过seajs.use()调用它。
通过导出暴露接口。这意味着不需要命名空间或全局变量。通过require引入依赖。这允许您包含依赖项,并且只需要关心当前模块的依赖项。注意力分离CMD 提出了依赖于邻近性的执行延迟。上面的例子中,用require引入的模块只有程序运行到这里才会被自动加载并执行。
同时还出现了一种叫spm(静态包管理器)的打包方式,听说支付宝项目中也使用了它。
UMD webpackUMD(Universal Module Definition)模式主要用于解决CommonJS模式和AMD模式代码不通用的问题,同时也支持经典的全局变量规范。
//使用Node、AMD 或浏览器创建模块。全局模式(function (root, Factory) { if (typeof define==='function' Define.amd) { //AMD 模式。注册为匿名函数。define(['b '], Factory); } else if ( typeof module==='object' module.exports) { //Node 和其他CommonJS 环境module.exports=Factory(require('b')); } else { //浏览器全局变量(根为window) root.returnExports=Factory(root.b); }}(typeof self !=='unknown' self : this, function (b) { //以某种方式使用b //定义一个返回值的模块导出(即,它可以返回对象或函数) return {};})); 判断定义是否为函数、define.amd 是否存在、是否为AMD 规范以及模块是否为An。确定module.exports 是否存在,以确定它是否是CommonJS 规范,如果都不存在,则将其设置为原始代码规范。这种模式通常在使用webpack 打包时使用。 Output.libraryTarget 指定模块将输出到的文件。
ES6 模块ECMAScript 2015 版本发布后,ES6 确定了一种新的模块加载方法,称为ES6 模块。与以往的方法有不同之处,也有相似之处。
既然是标准,以后就会得到很多浏览器的支持,在浏览器上使用起来也会很方便。它还支持在节点环境中运行。模块的进出口由进出口决定。可以与Commonjs 模块混合。 CommonJS 输出的是值的副本。 ES6 模块发出对加载时静态优化的值的引用。 CommonJS 模块在运行时加载以确定输出接口,ES6 模块在编译时确定输出接口。 ES6 模块功能由两个主要命令组成:导入和导出。 import命令用于导入其他模块提供的功能。 import命令用于标准化模块的外部接口。
导出的一些用途
//导出变量。 export var name='Drex'export varyear='2020'//导出一个对象(推荐) var name='Drex'varyear='2020'export { name,year}//导出一个函数或类import function add (a, b) {return a + b;}//导出默认命令。 import default function() {console.log('foo')} import import other module //常规命令import { name,year } from './module.js' //后缀.js不能省略//如果是模块发现是通过exportdefault命令导出的,从'./export-default.js'导入它。编辑模块后,以各种方式加载。
1.浏览器加载ES6模块。它也可以嵌入到网页中。
加载外部模块时,应记住以下几点:
代码在模块范围而不是全局范围运行。模块内的顶级变量从外部不可见。模块脚本自动采用严格模式,无论是否声明use strict。对于模块来说,可以使用import命令加载其他模块(不需要.js后缀,必须指定绝对或相对URL),也可以使用export命令输出外部接口,都可以这样做。在模块中,顶级this 关键字返回undefined 而不是指向窗口。这意味着在模块的顶层使用此关键字是没有意义的。如果同一个模块被加载多次,则只会执行一次。
2、Node要求ES6模块在加载Node时使用.mjs后缀文件名。这意味着只要在脚本文件中使用导入或导出命令,就必须使用.mjs 后缀。该功能仍处于实验阶段。如果安装Node V8.5.0 或更高版本,则必须使用--experimental-modules 参数启用此功能。
$ node --experimental-modules my-app.mjs Node导入命令仅支持异步加载本地模块(file:协议),不支持加载远程模块。