前端学习系列——(十一)JavaScript的模块化

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sinat_36521655/article/details/81119676

早期前端没有模块化的概念,基本就是直接在HTML页面上写或者JSP/PHP等页面上写。后面出现了传统的模块化方法通过添加全局变量、命名空间方式、闭包封装的形式实现模块化,但是不能解决依赖困难问题。后来出现了commonJS(同步加载)和AMD(异步加载)两种模块化规范,其中AMD主要用于前端开发,流行库为RequireJS,而commonJS用于后台和Node.js,CMD是SeaJS在推广时形成的规范。

AMD

1、仅仅需要在全局环境下定义require和define,不需要其他的全局变量

2、通过文件路径或模块自己声明的模块名定位模块

3、模块实现声明依赖,依赖的加载与执行均由加载器操作

4、提供了打包工具自动分析依赖并合并

典型用法:

define(function (require) {
    //通过相对路径获得依赖模块
    const bar = require('./bar');
    //模块产出
    return function () {
    //...
    };
});

CommonJS

相比于AMD的模块格式,CommonJS的模块格式更简洁,而且可以更方便地实现前后端代码共用,因为Node.js就是采用的CommonJS规范

典型用法:

//通过相对路径获得依赖模块
const bar = require('./bar');
//模块产出
module.exports = function () {
    //...
};
module.exports = {
    //...
};

CMD

CMD是SeaJS推广时形成的一种规范,它与AMD有点相似,但兼容CommoJS的模块。

典型用法:

define(function(require, exports, module) {
    var $ = require('jquery');
    var Spinning = require('./spinning');
    exports.doSomething = ...
    module.exports = ...
})

ES6模块化

相比于AMD或是CommonJS规范,ES6的模块化语句更清晰易懂,且其引用和暴露的方式更多样。

典型用法:

//通过相对路径获得依赖模块
import {bar, far} from './bar'
//模块产出
export let bar = 3;
export default function () {
    //...
}

 

对比CommonJS和ES6模块化

1、CommonJS模块输出的是一个值的复制,ES6模块输出的是值的引用(可被修改)

2、CommonJS模块是运行是加载,ES6模块是编译时输出接口

第一个差异主要是说,CommonJS的一旦输出,模块内部的变化不会影响到这个值;而JS引擎对脚本静态分析的时候,遇到模块加载命令import就会生成一个只读引用,等到脚本真正执行时,在根据这个只读引用到被加载的模块中取值,即ES6模块是动态引用,且不会缓存值,模块内部导致原始值变了,import加载的值也会跟着变。

第二个差异是因为CommonJS加载的是一个对象(即module.exports属性),该对象只有在脚本运行结束时才会生生。而ES6模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。

对比CMD和AMD

1、对于依赖的模块AMD是提前执行,CMD是延迟执行。不过RequireJS从2.0开始,也改成可以延迟执行(根据写法不同,处理方式不通过)。

2、CMD推崇依赖就近,AMD推崇依赖前置。

//AMD
define(['./a','./b'], function (a, b) {
    //依赖一开始就写好
    a.test();
    b.test();
});


//CMD
define(function (requie, exports, module) {
    //依赖可以就近书写
    var a = require('./a');
    a.test();

    //软依赖
    if (status) {
        var b = requie('./b');
        b.test();
    }
});

虽然 AMD也支持CMD写法,但依赖前置是官方文档的默认模块定义写法。

3、AMD的api默认是一个当多个用,CMD严格的区分推崇职责单一。例如:AMD里require分全局的和局部的。CMD里面没有全局的 require,提供 seajs.use()来实现模块系统的加载启动。CMD里每个API都简单纯粹。

部分内容引用《ES6标准入门第三版》以及博客https://blog.csdn.net/u010552788/article/details/51069451

猜你喜欢

转载自blog.csdn.net/sinat_36521655/article/details/81119676