前端经常使用4种模块化计划总结.md

JS降生之初面向简朴页面开辟, 没有模块的观点。厥后页面逐步庞杂, 人类组织到 IIFE 马上实行函数来模仿 模块;之前也有雅虎的实践,运用定名空间 作为模块名。末了衍生出 面向种种运用场景 的 JS 模块范例。比方:
面向浏览器的 AMD
面向Nodejs的 CommonJS
关于这类破裂状况ES范例也在全力弥合。 然则现在盛行的实践是 UMD情势。

1 AMD

AMD 是requirejs 推行产出的范例,重要用于浏览器环境,经由过程define和require这两个定义模块、挪用模块。

定义模块

   define("alpha", ["require", "exports", "beta"], function (require, exports, beta) {
       exports.verb = function() {
           return beta.verb();
           //Or:
           return require("beta").verb();
       }
   });
//  返回对象的匿名模块
 define(["alpha"], function (alpha) {
       return {
         verb: function(){
           return alpha.verb() + 2;
         }
       };
   });

挪用模块

require(['foo', 'bar'], function ( foo, bar ) {
        foo.doSomething();
});

define(function (require) {
        require(['a', 'b'], function (a, b) {
            //modules a and b are now available for use.
        });
    }); 

2 commonJS

Node 运用由模块组成,采纳 CommonJS 模块范例。
每一个文件就是一个模块,有本身的作用域。在一个文件内里定义的变量、函数、类,都是私有的,对其他文件不可见。
CommonJS 加载模块是同步的,所以只要加载完成才实行背面的操纵。像Node.js重要用于服务器的编程,加载的模块文件平常都已存在当地硬盘,所以加载起来比较快,不必斟酌异步加载的体式格局,所以CommonJS范例比较实用。但如果是浏览器环境,要从服务器加载模块,这是就必须采纳异步情势。所以就有了 AMD CMD 解决方案。

// a.js
// 相称于这里另有一行:var exports = module.exports;代码
exports.a = 'Hello world'; // 相称于:module.exports.a = 'Hello world';

// b.js
var moduleA = require('./a.js');
console.log(moduleA.a); // 打印出hello world

3 UMD

兼容 AMD 和 commonjs,也兼容 全局变量定义的 通用的模块化范例

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD
        define(['jquery'], factory);
    } else if (typeof exports === 'object') {
        // Node, CommonJS-like
        module.exports = factory(require('jquery'));
    } else {
        // Browser globals (root is window)
        root.returnExports = factory(root.jQuery);
    }
}(this, function ($) {
     function a(){}; // 私有要领,由于它没被返回 (见下面)
    function b(){}; // 大众要领,由于被返回了
    function c(){}; // 大众要领,由于被返回了
    // 暴露大众要领
    return {
        b: b,
        c: c
    }
}));

4 ES6 Module

ES6 在言语范例的层面上,完成了模块功用,而且完成得相称简朴,旨在成为浏览器和服务器通用的模块解决方案。其模块功用重要由两个敕令组成:export和import。
export敕令用于划定模块的对外接口,导出模块暴露的api ;import敕令用于输入其他模块供应的功用,引入其他模块。

/** 定义模块 math.js **/
var basicNum = 0;
var add = function (a, b) {
    return a + b;
};
export { basicNum, add };

/** 援用模块 **/
import { basicNum, add } from './math';
function test(ele) {
    ele.textContent = add(99 + basicNum);
}

5 ES6 模块与 CommonJS 模块的差别

  1. CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的援用。
  • CommonJS 模块输出的是值的拷贝,也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。
  • ES6 模块的运转机制与 CommonJS 不一样。JS 引擎对剧本静态剖析的时刻,碰到模块加载敕令import,就会天生一个只读援用。比及剧本真正实行时,再依据这个只读援用,到被加载的谁人模块内里去取值。换句话说,ES6 的import有点像 Unix 体系的“标记衔接”,原始值变了,import加载的值也会随着变。因而,ES6 模块是动态援用,而且不会缓存值,模块内里的变量绑定其地点的模块。
  1. CommonJS 模块是运转时加载,ES6 模块是编译时输出接口。
  • 运转时加载: CommonJS 模块就是对象;即在输入时是先加载全部模块,天生一个对象,然后再从这个对象上面读取要领,这类加载称为“运转时加载”。
  • 编译时加载: ES6 模块不是对象,而是经由过程 export 敕令显式指定输出的代码,import时采纳静态敕令的情势。即在import时能够指定加载某个输出值,而不是加载全部模块,这类加载称为“编译时加载”。

CommonJS 加载的是一个对象(即module.exports属性),该对象只要在剧本运转完才会天生。而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态剖析阶段就会天生。

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