模块化就是将系统分解成一个一个独立的功能模块,模块是独立的,可复用的,模块之间是解耦的。
CommonJS
Commonjs模块是一个可复用的js块,通过exports输出这个特定对象,其他模块通过require()引用此对象;
CommonJS支持无封装的模块(即没有定义的相关语句),把我们从AMD的define()封装中解放出来;
CommonJS只支持对象作为模块;
1 //package/lib is a dependency we require 2 var lib = require("package/lib"); 3 4 //behaviour for our module 5 function foo(){ 6 lib.log("hello world!") 7 } 8 9 //export (expose) foo to other modules 10 exports.foo = foo
Node应用由模块组成,采用commonjs模块规范,每个文件是一个模块,有自己的作用域。
commonjs规范规定,每个模块内部,module变量代表当前模块。这个变量是一个对象,它的
exports属性(module.exports)是对外的接口。require方法用于加载模块
1 //example.js 2 var x=5; 3 var foo = function(v){ 4 return v + x; 5 }; 6 module.exports.x = x; 7 module.exports.foo = foo; 8 9 //test.js 10 var example = require('./example.js'); 11 console.log(example.x);//5 12 console.log(example.foo(1))//6
不同的实现对require时的路径有不同要求,一般情况可以省略js
拓展名,可以使用相对路径,也可以使用绝对路径,甚至可以省略路径直接使用模块名(前提是该模块是系统内置模块)
commonJs模块特点:
1.所有代码都运行在模块作用域,不会污染全局作用域
2.模块可多次加载,但只在第一次加载运行,运行结果会存储在缓存,后面加载直接读取缓存,必须清除缓存才能让模块再次运行;
3.模块采用同步运行方式,按照在代码中出现但顺序进行加载
module.exports属性
module.exports属性表示当前模块对外输出但接口,其他文件加载该模块就是读取module.exports变量;
exports变量
为了方便,Node为每个模块提供一个exports变量,指向module.exports;这等同于在每个模块的头部都有一行一下命令:
1 var exports = module.exports
即,在对外输出模块接口时,可以向exports对象添加方法
1 exports.area = function (r) { 2 return Math.PI * r * r; 3 };
注意,不能直接将exports变量指向一个值,因为这样等于切断了exports
与module.exports
的联系。
即 exports = function(r){return Math.PI*r*r;}是无效的。
1 exports.hello = function(){ 2 return 'hele'; 3 } 4 module.exports = 'Hello world';
上面代码中,hello函数是无法输出的,因为下面module.exports被重新赋值了。
AMD(Asynchronous Module Defination,浏览器端js模块化)
异步模块定义规范,使用异步方式加载模块,通过define方法定义模块,require方法加载模块。
由于不是JavaScript原生支持,使用AMD规范进行页面开发需要用到对应的库函数RequireJS
,实际上AMD 是 RequireJS 在推广过程中对模块定义的规范化的产出;
异步加载模块,模块的加载不影响它后面语句的运行,所有依赖这个模块的语句,都定义在回调函数中,等加载完成
后,这个回调函数才会运行。
1 //定义模块myModule.js 2 define(['dependency'],function(){ 3 var name = 'Bily'; 4 function printName(){ 5 console.log(name); 6 } 7 return { 8 printName: printName 9 } 10 }) 11 //加载模块 12 require(['myModule],function(my){ 13 my.printName(); 14 })
requireJS定义了一个函数define,它是全局变量,用来定义模块
define(id?, dependencies? factory)
id:可选参数,用来定义模块的标识,如果没有提供该参数,就用脚本文件名(去掉扩展名)
dependencies: 当前模块依赖的模块名称数组
factory: 工厂方法,模块初始化要执行的函数或对象。如果是函数,它应该只被执行一次。如果是对象,此对象应该
为模块的输出值
在文件中使用require函数加载模块
require([dependencies],function(res){})
[dependencies] :第一个参数是数组,表示所依赖的模块
function : 第二个参数是一个回调函数,当前面指定的模块都加载成功后,它会被调用;加载的模块会以参数形式传入该函数,从而在回调函数内部可以使用这些模块;
require()函数在加载依赖的函数的时候是异步加载的,这样浏览器不会失去响应,它指定的回调函数,只有在前面的
模块都加载成功后,才会运行,解决了依赖性的问题;
模块化就是将系统分解成一个一个独立的功能模块,模块是独立的,可复用的,模块之间是解耦的。
CommonJS
Commonjs模块是一个可复用的js块,通过exports输出这个特定对象,其他模块通过require()引用此对象;
CommonJS支持无封装的模块(即没有定义的相关语句),把我们从AMD的define()封装中解放出来;
CommonJS只支持对象作为模块;
1 //package/lib is a dependency we require 2 var lib = require("package/lib"); 3 4 //behaviour for our module 5 function foo(){ 6 lib.log("hello world!") 7 } 8 9 //export (expose) foo to other modules 10 exports.foo = foo
Node应用由模块组成,采用commonjs模块规范,每个文件是一个模块,有自己的作用域。
commonjs规范规定,每个模块内部,module变量代表当前模块。这个变量是一个对象,它的
exports属性(module.exports)是对外的接口。require方法用于加载模块
1 //example.js 2 var x=5; 3 var foo = function(v){ 4 return v + x; 5 }; 6 module.exports.x = x; 7 module.exports.foo = foo; 8 9 //test.js 10 var example = require('./example.js'); 11 console.log(example.x);//5 12 console.log(example.foo(1))//6
不同的实现对require时的路径有不同要求,一般情况可以省略js
拓展名,可以使用相对路径,也可以使用绝对路径,甚至可以省略路径直接使用模块名(前提是该模块是系统内置模块)
commonJs模块特点:
1.所有代码都运行在模块作用域,不会污染全局作用域
2.模块可多次加载,但只在第一次加载运行,运行结果会存储在缓存,后面加载直接读取缓存,必须清除缓存才能让模块再次运行;
3.模块采用同步运行方式,按照在代码中出现但顺序进行加载
module.exports属性
module.exports属性表示当前模块对外输出但接口,其他文件加载该模块就是读取module.exports变量;
exports变量
为了方便,Node为每个模块提供一个exports变量,指向module.exports;这等同于在每个模块的头部都有一行一下命令:
1 var exports = module.exports
即,在对外输出模块接口时,可以向exports对象添加方法
1 exports.area = function (r) { 2 return Math.PI * r * r; 3 };
注意,不能直接将exports变量指向一个值,因为这样等于切断了exports
与module.exports
的联系。
即 exports = function(r){return Math.PI*r*r;}是无效的。
1 exports.hello = function(){ 2 return 'hele'; 3 } 4 module.exports = 'Hello world';
上面代码中,hello函数是无法输出的,因为下面module.exports被重新赋值了。
AMD(Asynchronous Module Defination,浏览器端js模块化)
异步模块定义规范,使用异步方式加载模块,通过define方法定义模块,require方法加载模块。
由于不是JavaScript原生支持,使用AMD规范进行页面开发需要用到对应的库函数RequireJS
,实际上AMD 是 RequireJS 在推广过程中对模块定义的规范化的产出;
异步加载模块,模块的加载不影响它后面语句的运行,所有依赖这个模块的语句,都定义在回调函数中,等加载完成
后,这个回调函数才会运行。
1 //定义模块myModule.js 2 define(['dependency'],function(){ 3 var name = 'Bily'; 4 function printName(){ 5 console.log(name); 6 } 7 return { 8 printName: printName 9 } 10 }) 11 //加载模块 12 require(['myModule],function(my){ 13 my.printName(); 14 })
requireJS定义了一个函数define,它是全局变量,用来定义模块
define(id?, dependencies? factory)
id:可选参数,用来定义模块的标识,如果没有提供该参数,就用脚本文件名(去掉扩展名)
dependencies: 当前模块依赖的模块名称数组
factory: 工厂方法,模块初始化要执行的函数或对象。如果是函数,它应该只被执行一次。如果是对象,此对象应该
为模块的输出值
在文件中使用require函数加载模块
require([dependencies],function(res){})
[dependencies] :第一个参数是数组,表示所依赖的模块
function : 第二个参数是一个回调函数,当前面指定的模块都加载成功后,它会被调用;加载的模块会以参数形式传入该函数,从而在回调函数内部可以使用这些模块;
require()函数在加载依赖的函数的时候是异步加载的,这样浏览器不会失去响应,它指定的回调函数,只有在前面的
模块都加载成功后,才会运行,解决了依赖性的问题;
CMD(Common Module Definition,通用模块定义)
cmd在模块定义和模块加载时机上和amd不同,并且CMD需要额外引入第三方的库文件,SeaJS;
seaJS推崇一个模块一个文件
define是一个全局函数,用来定义模块
define (id? , dependences?, factory)
参数id:可选,字符串类型,模块标识,如果没有提供参数,默认是文件名;
参数dependences:可选,字符串数组,当前模块依赖的模块,CMD推崇依赖就近;
参数factory:回调函数,工厂方法,初始化模块需要执行的函数或对象,如果为函数,它只被执行
一次,如果为对象,此对象会作为模块的输出值;
1 // cmd1.js 2 define(function(require,exports,module){ 3 // ... 4 module.exports={ 5 // ... 6 } 7 }) 8 9 // cmd2.js 10 define(function(require,exports,module){ 11 var cmd2 = require('./cmd1') 12 // cmd2.xxx 依赖就近书写 13 module.exports={ 14 // ... 15 } 16 })
对外提供接口:给exports对象添加成员,或者使用retutn直接向外提供接口
ADM和CMD区别,AMD提前执行依赖的模块即依赖前置,而后者是在用的之前,即依赖就近,只有在需要用到
某个模块的时候才requrie;
ES6模块化
ES6在语言标准的层面上,实现了模块功能,可取代commonjs和AMD规范,成为浏览器和服务器通用的模块解决方案;
ES6设计思想是尽量静态化,使得在编译时就能确定模块的依赖关系,以及输入和输出变量;而CommonJS和AMD
只能在运行时才能确定;
Es6模块不是对象,而是通过export命令显示指定输出的代码,再通过import命令输入;
// ES6模块
import { stat, exists, readFile } from 'fs';
上面代码实质是从fs模块加载3个方法,其他方法不加载,这种加载称为“编译时加载”或静态加载,即ES6可以在编译时就完成
模块加载,效率要比CommonJS模块的加载方式高,这也导致没法引用ES6模块本身,因为它不是对象。
ES6的模块自动采用严格模式,不管你有没有在模块头部加‘use strict’;
尤其注意,在模块中,顶层this指向undefined,即不可在顶层代码使用this;