开发者能够只须要实现业务逻辑,其余可加载别人写好的公共模块。javascript
script
引入文件<script src="jquery.js"></script>
<script src="jquery_scroller.js"></script>
<script src="bootstarp.js"></script>
<script src="commutil.js"></script>
<script src="main.js"></script>
复制代码
/** commutil.js(main.js)中: 模块就是实现特定功能的一组方法。 只要把不一样的函数简单地放在一块儿,就算是一个模块。 */
function fun1(){
...
}
function fun2(){
...
}
...
复制代码
缺点:前端
jquery
, 那么 jquery
就必定要先加载,var obj = new Object({
_count : 0,
fun1 : function (){
...
},
fun2 : function (){
...
}
});
复制代码
//调用方法
obj.fun1()
obj.fun2()
复制代码
缺点:java
obj._count = 1;
复制代码
使用”当即执行函数”(Immediately-Invoked Function Expression,IIFE
),能够达到不暴露私有成员的目的。node
var obj = (function() {
var _count = 0;
var fun1 = function() {
alert(_count)
}
var fun2 = function() {
alert(_count + 1)
}
return {
fun1, fun2
}
})()
复制代码
使用上面的写法,外部代码没法读取内部的_count变量。jquery
console.info(obj._count); //undefined
//调用内部函数能够
obj.fun1()
复制代码
jQuery
用的就是当即执行函数。require
导入模块【运行时加载】随着web
项目愈来愈大,JS
的代码量也与日俱增,因而社区就自发约定了几种模块化的方案:requirejs
遵循AMD
,seajs
遵循CMD
,node
的module
遵循CommonJS
规范,虽然写法上有所不一样,都是为了可以间接实现模块化的基础上保持较为一致的代码风格。程序员
Ryan Dahl
创造了node.js
项目,将javascript
语言用于服务器端编程。 这标志“Javascript模块化编程”正式诞生。node
编程最重要的思想之一就是模块,正是这个思想,让JavaScript
的大规模工程成为可能。js
界流行,也是基于此,随后在浏览器端,requirejs
和seajs
之类的工具包也出现了。require
统治了ES6
以前的全部模块化编程,即便如今,在ES6 module
被彻底实现以前,仍是这样。一个文件就是一个模块, 其内部定义的变量, 方法都处于该模块内, 不会对外暴露.es6
//新建 a.js, 导出sayHello和introSelf
// a.js
function sayHello(name) {
console.log(`Hello ${name}`)
}
function introSelf(name, age){
var msg = "myName is " + name + " and I'm " + age + " old";
console.log(msg);
}
module.exports.sayHello = sayHello
module.exports.introSelf = introSelf
/**或 module.exports = { sayHello: sayHello, introSelf: introSelf } */
//在 b.js 中引入 a 并调用
// b.js
const a = require('./a')
a.sayHello('Lucy')
a.introSelf('Lucy', 20)
复制代码
CommonJs
是同步加载的模块的, 在服务端(node
), 文件都在硬盘上, 因此同步加载也无所谓, 可是在浏览器端, 同步加载就体验很差了. 因此 CommonJs
主要使用于 node
环境下.synchronous
),只能采用”异步加载”(asynchronous
)。这就是AMD
规范诞生的背景。AMD
是Asynchronous Module Definition
的缩写,意思就是”异步模块定义”。它采用异步方式加载模块,模块的加载不影响它后面语句的运行。全部依赖这个模块的语句,都定义在一个回调函数中,等到加载完成以后,这个回调函数才会运行。CMD (Common Module Definition)
,阿里的玉伯提出, 是seajs推崇的规范,CMD
则是依赖就近,用的时候再require
(实现了按需加载)。 模块必须采用特定的define()
函数来定义。AMD
和CMD
模块必须采用特定的define()函数来定义。define(id?, dependencies?, factory)
/** - id:字符串,模块名称(可选) - dependencies: 是咱们要载入的依赖模块(可选), 使用相对路径。,注意是数组格式 - factory: 工厂方法,返回一个模块函数 */
复制代码
若是一个模块不依赖其余模块,那么能够直接定义在define()函数之中。web
AMD
推崇依赖前置(js能够方便知道依赖模块是谁,当即加载),而 CMD
推崇依赖就近(须要使用把模块变为字符串解析一遍才知道依赖了那些模块,这也是不少人诟病CMD
的一点)//AMD2.0以前
require(['./a', './b'], function(a, b) {
a.doSomething();
b.doSomething();
})
// AMD2.0以后
define(['./a', './b'], function(a, b) {
a.doSomething();
b.doSomething();
})
// CMD
define(function(require, exports, module) {
var a = require('./a');
a.doSomething();
var b = require('./b');
b.doSomething();
})
复制代码
require([module], callback);
复制代码
//若有一个math.js
require(['math'], function (math) {
math.add(2, 3);
});
复制代码
ES6 MODULES
【编译时加载】随着ES2015
的发布,官方标准定义了一种模块化的方案,那就是import
、export
。但是,标准毕竟是标准,各大浏览器和node终端要实现标准仍是有一段距离的。编程
export
和import
。export
命令用于规定模块的对外接口,import
命令用于输入其余模块提供的功能。export
关键字输出该变量。下面是一个 JS
文件,里面使用export
命令输出变量。// profile.js
export var firstName = 'Michael';
export var lastName = 'Jackson';
export var year = 1958;
复制代码
profile.js
文件,保存了用户信息。ES6
将其视为一个模块,里面用export命令对外部输出了三个变量。export
的写法,除了像上面这样,还有另一种。// profile.js
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;
export { firstName, lastName, year };
复制代码
import { firstName, lastName, year } from './profile.js';
//也能够用as
import { lastName as surname } from './profile.js';
复制代码
export
命令后面,使用大括号指定所要输出的一组变量。它与前一种写法(直接放置在var
语句前)是等价的,可是应该优先考虑使用这种写法。由于这样就能够在脚本尾部,一眼看清楚输出了哪些变量。export
命令除了输出变量,还能够输出函数或类(class
)。export function multiply(x, y) {
return x * y;
};
复制代码
multiply
。export
输出的变量就是原本的名字,可是可使用as
关键字重命名。function v1() { ... }
function v2() { ... }
export {
v1 as streamV1,
v2 as streamV2,
v2 as streamLatestVersion
};
复制代码
as
关键字,重命名了函数v1
和v2
的对外接口。重命名后,v2
能够用不一样的名字输出两次。export
命令规定的是对外的接口,必须与模块内部的变量创建一一对应关系。// 报错
export 1;
// 报错
var m = 1;
export m;
复制代码
// 写法一
export var m = 1;
// 写法二
var m = 1;
export {m};
// 写法三
var n = 1;
export {n as m};
复制代码
function
和class
的输出,也必须遵照这样的写法。// 报错
function f() {}
export f;
// 正确
export function f() {};
// 正确
function f() {}
export {f};
复制代码
import
命令的时候,用户须要知道所要加载的变量名或函数名,不然没法加载。可是,用户确定但愿快速上手,未必愿意阅读文档,去了解模块有哪些属性和方法。export default
命令,为模块指定默认输出。// export-default.js
export default function () {
console.log('foo');
}
复制代码
export-default.js
,它的默认输出是一个函数。import
命令能够为该匿名函数指定任意名字。// import-default.js
import customName from './export-default';
customName(); // 'foo'
复制代码
import
命令,能够用任意名称指向export-default.js
输出的方法,这时就不须要知道原模块输出的函数名。须要注意的是,这时import
命令后面,不使用大括号。export default
命令用在非匿名函数前,也是能够的。// export-default.js
export default function foo() {
console.log('foo');
}
// 或者写成
function foo() {
console.log('foo');
}
export default foo;
复制代码
foo
函数的函数名foo
,在模块外部是无效的。加载的时候,视同匿名函数加载。