js模块化

86 阅读2分钟

1.模块化的优点

减少命名污染,提高复用性、可维护性,减少耦合

2.立即执行函数

利用函数的块级作用域,立即执行。实现最简单的模块化

(function() {
    // 拥有独立作用域
})()
const module1 = (() => {
  let count = 0;
  return {
    increase: () => ++count;
  }
})();

module1.increase();

有额外的依赖时,以参数的传入

const module = ((moduleA, moduleB) => {
    
})(moduleA, moduleB)

3.AMD

通过异步加载+允许制定回调函数 通过define来定义模块,通过require来加载。 define(id?, [depends]?, callback) define 参数分别是 模块名,依赖模块,工厂方法; require([module], callback);

define('myModule', ['moduleA', 'moduleB'], (moduleA, moduleB) => {
    // 使用moduleA
    // 使用moduleB
})
require(['myModule'], (myModule) => {
    // 使用myModule
})

4.CMD

依赖就近原则,按需加载,在使用的时候才去引入

define('module', (require, exports, module) => {
    let $ = require('jquery');
    // 需要使用jquery相关逻辑

    let myModule = require('./myModule');
    // 需要使用myModule相关逻辑

})

缺点:依赖于打包,加载逻辑存在于每个模块中,扩大模块体积,打包体积变大 与AMD区别:AMD 推崇依赖前置、提前执行,CMD推崇依赖就近、延迟执行

5.CJS

commonjs规范,nodejs使用的规范;在运行时加载,值拷贝

  • 通过module + exports 对外暴露接口
  • 通过require来引入其他模块

    // 引入部分
    const moduleA = require(./moduleA);
    const moduleA = require(./moduleA);

    let count = 0;
    const increase = () => ++count;

    // 需要使用引用的相关逻辑……

    // 暴露接口部分
    exports.increase = increase;
    // 或者
    module.exports = {
        increase,
    }

注: 1.exports 是指向的 module.exports 的引用。类似于 var exports = module.exports。 require() 返回的是 module.exports 而不是 exports,所以当 module.exports和exports指向的不是同一块内存时,exports的内容就会失效

2.使用 require() 导入模块,导入后会缓存该模块,下次再加载该模块会直接从缓存中取出。所有缓存保存在 require.cache 中,可以使用 delete require.cache[moduleName] 方法删除缓存

// moduleA
export.name = 'A'
//引用
require('./moduleA.js')
console.log(require('./moduleA.js').name) // A
delete require.cache[require.resolve('./moduleA.js')]
console.log(require('./moduleA.js').name) //undefined

6.EMS

es6模块化通常被称为ES Module(或ES6 Module)。

使用上和CommonJS类似:

  • 使用 exportexport default 导出;
  • 使用 import 导入;
 // 引入
  import moduleA from './moduleA.js';

  let count = 0;
  //导出
  const increase = () => ++count;
  export { increase }
  // 默认导出
  // export default increase 

模板引入的时候

  <script type="module" src="esModule.js"></script>

还有一个动态导入的方法 import() ,调用时将返回一个 Promise 。使用方式可以如下:

import('./module.mjs').then((module) => {
    // TODO
});

commonjs和esmodule的区别

  • commonjs是运行时加载模块,ES6是在静态编译期间就确定模块的依赖
  • commonjs是同步加载模块,ES6是异步加载
  • commonjs是一个值拷贝,会对加载结果进行缓存,一旦内部再修改这个值,则不会同步到外部。ES6是导出的一个引用,内部修改可以同步到外部。