一览js模块化:从CommonJS到ES6

本文由云+社区宣告

模块化是指把一个庞杂的体系剖析到一个一个的模块。

模块化开辟的长处

(1)代码复用,让我们更方便地举行代码治理、同时也便于背面代码的修正和保护。

(2)一个零丁的文件就是一个模块,是一个零丁的作用域,只向外暴露特定的变量和函数。如许能够防止污染全局变量,削减变量定名争执。

js模块化范例有:CommonJS、AMD、CMD、ES6的模块体系。本文将顺次引见下每一个范例。

0.初期:用script来引入js模块

<script type="text/javascript" src="a.js"></script>
<script type="text/javascript" src="b.js"></script>
<script type="text/javascript" src="c.js"></script>
<script type="text/javascript" src="d.js"></script>

瑕玷:

(1)加载的时刻会住手衬着网页,引入的js文件越多,网页落空相应的时候越长;

(2)会污染全局变量;

(3)js文件之间存在依靠关联,加载是有递次的,依靠性最大的要放到末了去加载;当项目范围较大时,依靠关联变得扑朔迷离。

(4)要引入的js文件太多,不美观,代码难以治理。

1.CommonJS 范例

服务器端模块的范例,由nodejs推行运用。该范例的中心头脑是:许可模块经由过程require要领来同步加载所要依靠的其他模块,然后经由过程 exports 或module.exports 来导出须要暴露的接口。

CommonJS 还能够细分为 CommonJS1 和 CommonJS2,辨别在于 CommonJS1 只能经由过程 exports.xx = xx 的体式格局导出,CommonJS2 在 CommonJS1 的基础上加入了module.exports = xx 的导出体式格局。 CommonJS 通常指 CommonJS2。

采纳CommonJS 范例导入导出:

// 导出
module.exports = moduleA.someFunc;
// 导入
const moduleA = require('./moduleA');

实例:

//math.js
var num = 0;
function add(a, b) {
  return a + b;
}
module.exports = {
  //须要向外暴露的变量、函数
  num: num,
  add: add
}

能够如许加载:

//引入自定义的模块时,参数包括途径,可省略.js
//引入中心模块时,不须要带途径,如var http = require("http");
var math = require('./math');
math.add(1, 2)//3

实际上,从上面的例子就能够看出,math.add(1,2)必需要守候math.js加载完成,即require是同步的。

在服务器端,模块文件保存在当地磁盘,守候时候就是磁盘的读取时候。但关于浏览器而言,因为模块都放在服务器端,守候时候取决于网上的快慢。因而更合理的计划是异步加载模块。

瑕玷:

(1)不能并行加载模块,会壅塞浏览器加载;

(2)代码没法直接运转在浏览器环境下,必需经由过程东西转换成规范的 ES5;

2.AMD和require.js

AMD:异步模块定义。上面已引见过,CommonJS是服务器端模块的范例,重要是为了JS在后端的表现制订的,不太合适前端。而AMD就是要为前端JS的表现制订范例。因为不是JavaScript原生支撑,运用AMD范例举行页面开辟须要用到对应的库函数,也就是require.js(另有个js库:curl.js)。实际上AMD 是 require.js在推行过程当中对模块定义的范例化的产出。

AMD采纳异步体式格局加载模块,模块的加载不影响它背面语句的运转。一切依靠这个模块的语句,都定义在一个回调函数中,比及加载完成以后,这个回调函数才会运转。

require.js也采纳require()语句加载模块,然则差别于CommonJS:

// 定义一个模块
define('module', ['dep'], function (dep) {
  return exports;
});

// 导入和运用
require(['module'], function (module) {
});

上面示例中的代码改写成AMD情势:

math.js定义一个模块:

define('math', ['jquery'], function (jquery) {//引入jQuery模块
  return {
    add: function (x, y) {
      return x + y;
    }
  };
});

导入和运用:

require(['math'], function (math) {
  math.add(1, 2)
})

math.add()与加载math模块不是同步的,不会壅塞浏览器的加载。

3.CMD和sea.js

CMD:通用模块定义。

国内的玉伯大佬写了sea.js,实际上CMD就是 sea.js在推行过程当中对模块定义的范例化的产出。

define(function (require, exports, module) {
  // 模块代码
});

申明:

require:能够把其他模块导入进来的一个参数;

exports:能够把模块内的一些属性和要领导出的;

module: 是一个对象,上面存储了与当前模块相关联的一些属性和要领。

上面示例中的代码改写成AMD情势:

define(function (require, exports, module) {
  var add = function (a, b) {
    return a + b;
  }
  exports.add = add;
})

//导入和运用
seajs.use(['math.js'], function (math) {
  var sum = math.add(1, 2);
});

CMD与AMD的差别的在于:

(1)AMD推重依靠前置;CMD推重依靠就近,只要在用到某个模块的时刻再去require:

//AMD推重的依靠关联前置:在定义模块时就要声明要依靠的模块
define(['a', 'b', 'c', 'd'], function (a, b, c, d) { // 依靠必需一开始就写好
  a.doSomething()
  // 此处省略100行
  ...
  b.doSomething()
  ...
})

//CMD推重依靠就近,按需加载,只要在用到某个模块时再去require
define(function (require, exports, modules) {
  var a = require('a');
  a.doSomething();
  // 此处省略100行
  ...
  var b = require("b");//按需加载
  b.doSomething();
  ...
})

(2)AMD 的 API 默许是一个当多个用,CMD 的 API 严厉辨别,推重职责单一。

关于依靠的模块,AMD是提早实行,CMD是耽误实行。

详细细节可点击参考

4.ES6模块化

ES6在言语的层面上完成了模块化。浏览器厂商和 Node.js 都宣告要原生支撑该范例。它将逐步庖代 CommonJS 和 AMD 范例,成为浏览器和服务器通用的模块解决计划。

在 ES6 中,运用export关键字来导出模块,运用import关键字援用模块。然则浏览器还没有完整兼容,须要运用babel转换成ES5。

// 导出
export function hello() { };
export default {
  // ...
};
// 导入
import { readFile } from 'fs';
import React from 'react';

运用import导入模块时,须要晓得要加载的变量名或函数名。

在ES6中还供应了export default,为模块指定默许输出.对应导入模块import时,不须要运用大括号。

上面示例中的代码改写成ES6情势:

//math.js
var num = 0;
var add = function (a, b) {
  return a + b;
};
export { num, add };

//导入
import { num, add } from './math';
function test(ele) {
  ele.textContent = add(1 + num);
}

瑕玷

浏览器还没有完整兼容,必需经由过程东西转换成规范的 ES5 后才一般运转。

5.小结

本文从script引入js文件讲起,到服务器端模块的范例CommonJs,再到推重依靠前置的浏览器端模块的范例AMD、推重依靠就近的浏览器端模块的范例CMD,末了引见了ES6的模块化。每一个引见中都有各范例基础的用法和一个示例。若有题目,迎接斧正。

此文已由作者受权腾讯云+社区宣布

    原文作者:腾讯云加社区
    原文地址: https://segmentfault.com/a/1190000017492700
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞