Javascript不是一种模块化编程语言,它不支持”类”(class),更别说”模块”(module)了。开发者们做了很多努力,在现有的运行环境中,实现”模块”的效果。
- function a(){
- ...
- };
- function b(){
- ...
- };
- function c(){
- ...
- };
后果:
- var obj = {
- a:1,
- b:function(){
- ...
- }
- };
优点:
1、解决了变量污染的问题;
2、保证模块名唯一即可,建立同一模块内的成员的关系。
缺点:
1、暴露所有模块成员,内部状态可以被外部任意改写。
- obj.a = 100;
- (function(){
- var obj = {
- a:1,
- b:function(){
- ...
- }
- };
- })();
优点:
1、解决暴露所有模块成员,内部状态可以被外部任意改写的问题。
缺点:
1、所需依赖还是得外部提前提供。
2009年,对js是历史性的一年,nodeJS横空出世,让js跑在服务端,如果说js在浏览器上面可以没有模块,但是在服务端没有模块的思想是万万不能容忍的。由Mozilla 的工程师 Kevin Dangoor 在2009年1月创建了commonJS规范。
- //创建模块 one.js
- var a = 'aaaa';
- function b() {
- console.log(a);
- };
- module.exports = {
- a: a,
- b: b
- };
- //加载模块 two.js
- var x = require('./one.js');
- x.b();
优点:
1、所有代码都运行在模块作用域,不会污染全局作用域;
2、独立性是模块的重要特点就,模块内部最好不与程序的其他部分直接交互;
3、模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存;
4、模块加载的顺序,按照其在代码中出现的顺序。
node推广了commonJS规范,但是在浏览器中又出现了很多问题
问题:
浏览器资源的加载方式与服务端完全不同。服务端require一个模块,直接就从硬盘或者内存中读取了,消耗的时间可以忽略。而浏览器则不同,需要从服务端来下载这个文件,然后运行里面的代码才能得到API,需要花费一个http请求,也就是说,require后面的一行代码,需要资源请求完成才能执行。
由于浏览器端是以插入script标签的形式来加载资源的(ajax方式不行,有跨域问题)没办法让代码同步执行,所以像commonjs那样的写法会直接报错。
这意味着要想适应浏览器,规范还要改进!!!
一个
Modules/Wrappings规范出现了。
经过一番谈论、修改(过程忽略),AMD思想出现了…AMD(Asynchronous Module Definition):
具体Api请参见:AMD (中文版)
- //定义和暴露模块
- define("xxx", ["xxx", "xxx"], function(x, x) {
- return ... ;
- });
- //加载模块
- require(["xxx", "../xxx"], function(xxx, xxx) {
- xxxx
- });
说完AMD,就不得不提把AMD在浏览器实现的RequireJS。
RequireJS是一个JavaScript文件和模块加载器,采用AMD规范。
参考文件:RequireJS
CMD(Common Module Definition):
- //定义和暴露模块
- define('xxx', ['xxx'],
- function(xxx, xxx, xxx) {
- return...;
- });
- //加载模块
- define(function(require, exports) {
- // 获取模块 a 的接口
- var a = require('./a');
- // 调用模块 a 的方法
- a.doSomething();
- });
既然CommonJs和AMD风格一样流行,似乎缺少一个统一的规范。所以人们产生了这样的需求,希望有支持两种风格的“通用”模式,于是通用模块规范(UMD)诞生了。
本文主要记述模块的思想在浏览器的实现过程,不是一篇详细的Api教程。
来源: https://juejin.im/entry/5a2a3c895188252da05357d5