JS模块简介
js模块化,简单说就是将系统或者功能分隔成单独的、互不影响的代码片段,经过严格定义接口,使各模块间互不影响,且可以为其他所用。
常见的模块化有,C中的include (.h)文件、java中的import等。
为什么JS需要模块
很显然,没有模块我们也可以实现同样的功能,为什么我们还要使用模块来写js代码呢?下面几点是模块化给我们带来的一些变化:
ES5及之前的模块系统
在ES5及之前版本,还没有原生的模块语法。不过这并不代表ES5之前,前端没有使用模块。简单介绍两种:IIFE、Revealing Module.
IIFE
Immediately Invoked Function Expression,立即执行函数表达式。
(function(){ // ... })()
看上面的代码,IIFE可以说成是一个在定义的时候就执行的匿名函数。注意函数是先被”()”包起来了,然后后面紧跟”()”表示执行函数。如果是以下代码,将会报错:
function(){ console.log('test'); }() // => Uncaught SyntaxError: Unexpected token )
这种写法表示,先定义一个匿名函数,然后再去解析”()”。由于在第一行”function”出现在首位,这表明此处定义一个函数,函数后紧跟”()”,此时表示单独解析”()”,就会报出上面的错误信息,因此需要先将函数定义包裹起来。
“(function…)”这种写法表示执行”()”内部代码,并返回该语句执行结果,此处返回结果为该函数,后面紧跟”()”即表示执行该函数。IIFE可以帮助我们做到:
显而易见,这种编码方式并没有提供良好的机制来解决依赖管理问题。
Revealing Module
根据字面暂解释为揭示模式,与IIFE形式类似,但是提供了一个返回值。方便集中管理公有的api,使模块、公用api更加简洁清晰。
// Expose module as global variable var singleton = function(){ // Inner logic function sayHello(){ console.log('Hello'); } // Expose API return { sayHello: sayHello } }()
稍微注意下,上面的代码,我们并没有用”()”去包裹,因为关键字”function”并不在该行的开头。
我们可以像下面这样使用模块api:
// Access module functionality singleton.sayHello(); // => Hello
当然,我们也可以以构造函数形式导出:
// Expose module as global variable var Module = function(){ // Inner logic function sayHello(){ console.log('Hello'); } // Expose API return { sayHello: sayHello } }
请注意,上面函数在定义的时候并没有执行。
我们可以这么使用它:
var module = new Module(); module.sayHello(); // => Hello
与IIFE一样,揭示模式并没有提供良好的解决依赖管理的方案。
更多模块化解决方案
ES6或者ES2015,自带原生的模块语法。
在这之前,有以下几种常见的用于模块化的解决方案:
AMD
AMD,Asynchronous Module Definition,异步模块定义。AMD形式被用于浏览器端,使用”define”来定义模块依赖:
//Calling define with a dependency array and a factory function define(['dep1', 'dep2'], function (dep1, dep2) { //Define the module value by returning a value. return function () {}; });
CMD
CMD,Common Module Definition,通用模块定义。该规范由国内大神玉伯提出,与AMD区别在与AMD是依赖关系前置,有该依赖就必须先加载依赖,CMD是按需加载。
// CMD define(function(require, exports, module) { var a = require('./a') a.doSomething() // 此处略去 100 行 var b = require('./b') // 依赖可以就近书写 b.doSomething() // ... }) // AMD 默认推荐的是 define(['./a', './b'], function(a, b) { // 依赖必须一开始就写好 a.doSomething() // 此处略去 100 行 b.doSomething() ... })
CommonJs
CommonJs在Node.js中用的较多,使用”require”来定义依赖,使用”module.exports”来定义模块:
var dep1 = require('./dep1'); var dep2 = require('./dep2'); module.exports = function(){ // ... }
UMD
UMD,Universal Module Definition,通用模块定义。可以用于浏览器端与Node.js端:
(function (root, factory) { if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['b'], factory); } else if (typeof module === 'object' && module.exports) { // Node. Does not work with strict CommonJS, but // only CommonJS-like environments that support module.exports, // like Node. module.exports = factory(require('b')); } else { // Browser globals (root is window) root.returnExports = factory(root.b); } }(this, function (b) { //use b in some fashion. // Just return a value to define the module export. // This example returns an object, but the module // can return a function as the exported value. return {}; }));
System.register
System.register方式设计初衷主要是为了在ES5中能够支持ES6模块语法:
import { p as q } from './dep'; var s = 'local'; export function func() { return q; } export class C { }
ES6 module
ES6中自带原生的模块语法,使用关键字”export”来导出模块的公用api:
// lib.js // Export the function export function sayHello(){ console.log('Hello'); } // Do not export the function function somePrivateFunction(){ // ... }
以关键字”import”来导入模块:
import { sayHello } from './lib'; sayHello(); // => Hello
目前各浏览器对ES6的支持度不一,因此我们现在需要使用编译器,像Babel,来将ES6的代码编译成ES5的形式。
模块加载器
一个模块加载器可以理解模块,并以固定的形式来加载模块。
模块加载器工作在运行时,流程大致如下:
一些比较常见的模块加载器有:
模块打包
模块打包可以替换模块加载器。
然而,相比模块加载器,模块打包动作是在编译时运行的:
截止目前,比较常用的模块打包方案有以下两种:
总结
为了在现代js开发环境中更好的使用这些工具,你首先需要知道模块、模块化解决方案、模块加载、模块打包之前的区别。
模块是一段封装好的代码,可以以公用api形式导出并在其他代码中被加载和调用;
模块化解决方案或者模块化思想,实际含义是定义一个模块的语法。由于定义语法的差异,目前常用的有AMD、CMD、CommonJS、UMD等;
模块加载,在运行期解析和加载模块。常见的有RequireJS、SeaJS、SystemJS和jspm;
模块打包,其替换了模块加载的概念,在编译期间生成一个所有代码整合后的bundle.js文件。常见的有Browserify和Webpack。
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家小牛知识库的支持。
本文向大家介绍Lua中的模块与module函数详解,包括了Lua中的模块与module函数详解的使用技巧和注意事项,需要的朋友参考一下 很快就要开始介绍Lua里的“面向对象”了,在此之前,我们先来了解一下Lua的模块。 1.编写一个简单的模块 Lua的模块是什么东西呢?通常我们可以理解为是一个table,这个table里有一些变量、一些函数… 等等,这不就是我们所熟悉的类吗? 没错,和类很像(实际
本文向大家介绍Node.js模块加载详解,包括了Node.js模块加载详解的使用技巧和注意事项,需要的朋友参考一下 JavaScript是世界上使用频率最高的编程语言之一,它是Web世界的通用语言,被所有浏览器所使用。JavaScript的诞生要追溯到Netscape那个时代,它的核心内容被仓促的开发出来,用以对抗Microsoft,参与当时白热化的浏览器大战。由于过早的发布,无可避免的造成了它的
Enable loadable module support 可加载模块支持 Enable loadable module support CONFIG_MODULES 打开可加载模块支持,可以通过"make modules_install"把内核模块安装在/lib/modules/中.然后可以使用 modprobe, lsmod, modinfo, insmod, rmmod 等工具进行各种模块
定义 页面局部处于等待异步数据或正在渲染过程时,合适的加载动效会有效缓解用户的焦虑。 图片展示 代码演示 import Load from 'pile/dist/components/load', <Load show={true} timeOut={3000} loadType='carFace' loadSize='small' /> 属性 参数 描述 数据类型 默认值 s
在本章中,我们将研究Joomla中的Syndicate Module 。 Syndicate模块有助于为页面创建RSS源链接。 它允许用户为当前页面创建新闻源。 辛迪加模块 以下是在Joomla中编辑现有Syndicate模块的简单步骤。 Step (1) - 在Joomla管理员中单击Extension → Module Manager ,将显示以下屏幕。 Step (2) - 接下来,单击“
稳定性: 2 - 稳定的 Node.js 有一个简单的模块加载系统。 在 Node.js 中,文件和模块是一一对应的(每个文件被视为一个独立的模块)。 例子,假设有一个名为 foo.js 的文件: const circle = require('./circle.js'); console.log(`半径为 4 的圆的面积是 ${circle.area(4)}`); 在第一行中,foo.js 加