什么是模块化?

模块化是一种处理复杂系统分解为更好的可管理块的方式。简单来说就是解耦,简化开发,一个模块就是实现特定功能的文件,可以更方便的使用别人的代码,想要什么功能,就加载什么模块,模块开发需要遵从一定的规范。

CommonJS规范

CommonJS就是一个JavaScript模块化的规范,是用在服务器端的node的模块规范,前端的webpack也是相对CommonJS原生支持的。

特点:1、模块输出的是一个值的拷贝,模块是运行时加载,同步加载。 2、commonjs模块的顶层this只向当前模块。

有2个API:

  • require:加载所要依赖的其他模块
  • module.exports或者exports:对外暴漏的接口。 注意 (1).exports和module.exports的区别:exports是对module.exports的引用,不能直接给exports赋值,直接赋值无效,结果是一个空对象,module.exports可以直接赋值。示例:
module.exports = 123 //123
module.exports = function(){} //function
exports = 123 //{}
exports = function(){} //{}

(2).一个文件不能写多个module.exports,如果多写,对外暴漏的街口是最后一个。 (3).模块如果没有指定使用module.exports 或者 exports对外暴漏接口时,在其他文件就引用该模块,得到的是一个空对象{}。

AMD规范

AMD即Asynchronous Module Definition,中文名称是:“异步模块定义”的意思。它是一个在浏览器端模块化开发的规范,AMD是RequireJS在推广过程中对模块定义规范化产出,所以AMD规范的实现,就算require.js

特点:异步加载,不阻塞页面的加载,能并行加载多个模块,但不能按需加载,必须提前加载所需要的以来。

AMD的规范中两个重要的API:

define(id?,[]?,callback): //定义声明模块,参数id 模块id标识(可选),参数二是一个数组[]可选,依赖其他模块,最后是一个回调函数。 require([module],calback)://加载模块,参数一是一个数组,指定加载的模块,参数二回调函数,模块加载完成后执行。

还有一个配置API:

//首先,引入requiresJS
 //requirejs.html
   <!DOCTYPE html>
//Math.js
// 定义了AMD 模式的模块,并且引入了jquery 模块 (这里的jquery属于AMD模式)
define(['jquery'],function(_){
    //define(['moudel1','moudel2'],callback())
    //如果一个模块不依赖其他模块,直接使用define()函数写,
    //如果一个模块依赖其他模块,define()第一个参数是数组
    //回调函数的参数对应第一个参数数组的值,按顺序
    console.log(_);//ƒ (a,b){return new m.fn.init(a,b)}
  return { 
        add:function(x,y){
            return x+y;
        },
    }
})

// index.js (主入口)
//配置好加载路径
 require.config({
    baseUrl:"../js",
    paths:{    
        "index":"index", // 主入口文件 index: 
     "jquery":"jquery.min",// jquery 库,符合AMD模式(1.7 版本以上符合AMD)
        "maths":"Math", //自定义AMD 模式的模块
    }
})

//加载maths.js
   require(["maths"],function(_math){
    console.log( _math); // {add: ƒ }
})
CMD规范

CMD规范是由阿里的玉伯提出的,实现js库为sea.js,它和require非常类似,及一个js文件是一个模块,但是CMD加载的方式更加优秀,是通过按需加载的方式,而不是必须在模块开始加载所有的依赖。

seajs.config({
	alias:{'jquery',:'http://xxxx'}
});
define(function(require,exports,module){
	var $ = require('jquery')
})
seajs.use(['./a','./b'],function(a,b){

	a.doSomething()
	
	b.doSomething()
	
})
es6的module规范

ES6在语言标准层面上,实现了模块功能,而且非常简单,ES6到来,完全取代了CommonJS和AMD规范,成为浏览器和服务器通用的模块解决方案。由Vue,Angular,React这些mvvm模式的框架发展,让前端的编程变的模块化,组件化。

特点:1、ES6模块中,顶层的this指向undefined,即不应该在顶层代码使用this。 2、自动采用严格模式“use strict”。遵循严格模式的要求。 3、ES6模块的设计思想是尽量的静态化,编译时加载,或者静态加载,编译时输出接口。 4、ES6模块的export和import命令可以出现在模块的任何位置,但是必须处于顶层。如果处于块级作用域,就会报错。 5、ES6模块输出的是值的引用

模块功能主要由两个命令构成:export和import 1、export:用于规定模块的对外接口 2、import:用于输入其他模块提供的功能

1、export命令

export.js
//
export function fn (x,y){
 return x + y
}
export var m = 1

export class calss1{}

function v1(){}
function v2(){}

export {
v1 as streamv1,
v2 as streamv2
}

2、import命令

main.js

import { m , fn , streamv1} from './require.js'

import * as all from './export.js'

3、export default 命令 本质上,export default就是输出一个叫做 default 的 变量 或 方法

export default function foo (){
	console.log('foo')
}
//或者写成
function foo(){
	console.log('foo')
}
export default foo

// import 
import myfoo form './export-default.js'

比较一下默认输出和正常输出

exports default function a1(){}
	
	import a1 from ''
	
	export  function a2 (){}
	
	import {a2} from ''

分析:上面两组代码 第一组是使用export default时,对应的import语句不需要使用大括号 第二组是不使用export default时 , 对应的import 语句需要使用大括号