一文让你彻底搞清楚javascript中的require、import与(2)

AMD是”Asynchronous Module Definition”的缩写,意思就是”异步模块定义”。它采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。

模块必须采用特定的define()函数来定义。

define(id?, dependencies?, factory)

id:字符串,模块名称(可选)

dependencies: 是我们要载入的依赖模块(可选),使用相对路径。,注意是数组格式

factory: 工厂方法,返回一个模块函数

如果一个模块不依赖其他模块,那么可以直接定义在define()函数之中。

// math.js   define(function (){     var add = function (x,y){       return x+y;     };     return {       add: add     };   });

如果这个模块还依赖其他模块,那么define()函数的第一个参数,必须是一个数组,指明该模块的依赖性。

define(['Lib'], function(Lib){     function foo(){       Lib.doSomething();     }     return {       foo : foo     };   });

当require()函数加载上面这个模块的时候,就会先加载Lib.js文件。

AMD也采用require()语句加载模块,但是不同于CommonJS,它要求两个参数:

require([module], callback);

第一个参数[module],是一个数组,里面的成员就是要加载的模块;第二个参数callback,则是加载成功之后的回调函数。如果将前面的代码改写成AMD形式,就是下面这样:

require(['math'], function (math) {  math.add(2, 3); });

math.add()与math模块加载不是同步的,浏览器不会发生假死。所以很显然,AMD比较适合浏览器环境。

目前,主要有两个Javascript库实现了AMD规范:require.jscurl.js

CMD规范

一文让你彻底搞清楚javascript中的require、import与

CMD (Common Module Definition), 是seajs推崇的规范,CMD则是依赖就近,用的时候再require。它写起来是这样的:

define(function(require, exports, module) { var clock = require('clock'); clock.start(); });

CMD与AMD一样,也是采用特定的define()函数来定义,用require方式来引用模块

define(id?, dependencies?, factory)

id:字符串,模块名称(可选)

dependencies: 是我们要载入的依赖模块(可选),使用相对路径。,注意是数组格式

factory: 工厂方法,返回一个模块函数

define('hello', ['jquery'], function(require, exports, module) { // 模块代码 });

如果一个模块不依赖其他模块,那么可以直接定义在define()函数之中。

define(function(require, exports, module) { // 模块代码 });

注意:带 id 和 dependencies 参数的 define 用法不属于 CMD 规范,而属于 Modules/Transport 规范。

CMD与AMD区别

AMD和CMD最大的区别是对依赖模块的执行时机处理不同,而不是加载的时机或者方式不同,二者皆为异步加载模块。

AMD依赖前置,js可以方便知道依赖模块是谁,立即加载;

而CMD就近依赖,需要使用把模块变为字符串解析一遍才知道依赖了那些模块,这也是很多人诟病CMD的一点,牺牲性能来带来开发的便利性,实际上解析模块用的时间短到可以忽略。

现阶段的标准

一文让你彻底搞清楚javascript中的require、import与

ES6标准发布后,module成为标准,标准使用是以export指令导出接口,以import引入模块,但是在我们一贯的node模块中,我们依然采用的是CommonJS规范,使用require引入模块,使用module.exports导出接口。

export导出模块

export语法声明用于导出函数、对象、指定文件(或模块)的原始值。

注意:在node中使用的是exports,不要混淆了

export有两种模块导出方式:命名式导出(名称导出)和默认导出(定义式导出),命名式导出每个模块可以多个,而默认导出每个模块仅一个。

export { name1, name2, …, nameN }; export { variable1 as name1, variable2 as name2, …, nameN }; export let name1, name2, …, nameN; // also var export let name1 = …, name2 = …, …, nameN; // also var, const export default expression; export default function (…) { … } // also class, function* export default function name1(…) { … } // also class, function* export { name1 as default, … }; export * from …; export { name1, name2, …, nameN } from …; export { import1 as name1, import2 as name2, …, nameN } from …;

name1… nameN-导出的“标识符”。导出后,可以通过这个“标识符”在另一个模块中使用import引用

default-设置模块的默认导出。设置后import不通过“标识符”而直接引用默认导入

-继承模块并导出继承模块所有的方法和属性

as-重命名导出“标识符”

from-从已经存在的模块、脚本文件…导出

命名式导出

模块可以通过export前缀关键词声明导出对象,导出对象可以是多个。这些导出对象用名称进行区分,称之为命名式导出。

export { myFunction }; // 导出一个已定义的函数 export const foo = Math.sqrt(2); // 导出一个常量

我们可以使用*和from关键字来实现的模块的继承:

export * from 'article';

模块导出时,可以指定模块的导出成员。导出成员可以认为是类中的公有对象,而非导出成员可以认为是类中的私有对象:

var name = 'IT笔录'; var domain = 'http://itbilu.com'; export {name, domain}; // 相当于导出 {name:name,domain:domain}

模块导出时,我们可以使用as关键字对导出成员进行重命名:

var name = 'IT笔录'; var domain = 'http://itbilu.com'; export {name as siteName, domain};

注意:下面的语法有严重错误的情况:

// 错误演示 export 1; // 绝对不可以 var a = 100; export a;

export在导出接口的时候,必须与模块内部的变量具有一一对应的关系。直接导出1没有任何意义,也不可能在import的时候有一个变量与之对应

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wyzdjs.html