为什么需要amd规范

简介:

今天主要说说AMD规范在Web环境里的应用,以及为什么采用AMD规范.想了解AMD规范的可以点击这里


what AMD?

  • 规定 define 来定义一个模块
  • 规定 require 来请求一个模块
  • 规定 exports 来导出一个模块对外公共的API
  • 约定通用的模块依赖规范

使用AMD之前是怎么实现一个模块的呢?

下面是一个简单模块的例子.

(function(global){
    var module = {
        prop: 'name',
        method: function(){ // do stuff}
    }
    global.moduleName = module;
})(this);

基本上没有使用AMD之前一般都是这样实现一个模块的:

  • 定义一个立即执行的函数来导出一个模块公共API
  • 使用script标签来加载模块
  • 使用一定的script加载顺序来控制模块之前的依赖

当项目很大的时候,这种方式的模块开发几乎不能维护,而且部署的时候也是一个大问题,通常需要对业务进行脚本化来简化部署.

另一个模块规范COMMONJS

这里COMMONJS模块先简写为CJS.

起初CJS规范是在NodeJS里使用的,看下面的一段简单的代码.

var _ = require('underscore');
exports.module = {
    find: function(){ // do stuff use _ }
}

在CJS眼里,模块是阻塞的方式来加载的,这样才能保证后面的代码可以取得模块实例,但是这个跟浏览器是天生的不兼容,因为浏览器端的脚本都是异步加载的,像上面的代码在浏览器端就会报错,假如在exports里的使用_的话。

有人说,可以在浏览器端模拟require来异步加载脚本,确实,使用xhr然后解析脚本内容来获取模块实例,但是这种方式有很多缺点,详情可以看我之前写的文章,为什么需要web模块

说说AMD

先上一个以AMD规范定义的模块代码

define(['underscore'], function(_){
    var module = {
        // do stuff use _
    };
    return module;
});

相比较于普通的立即函数,以define方式定义的模块没有在全局下增加额外的东西,而且是传递数组方式的参数来解决模块依赖的问题,最后一个回调函数是在前面所有的依赖加载完成之后执行.

AMD是上面那种以‘XHR和动态解析脚本内容’方式的改进,提高了可编程性以及调试,方便项目构建

AMD模块支持定义模块名称,默认第一个参数是模块名称,看下面的代码

define('demoMd', ['underscore'], function(_){
    var module = {
        // do stuff use _
    }
    return module;
});

其实最佳的模块定义规范是,模块名称是可以不写的,这样可以提高模块的重用性,而且一个文件最后只定义一个模块,这样相同的模块定义文件可以保证它的独立性,最终的模块名称会根据不同的AMD规范实现在内部定义的.

使用模块名称的地方,其实只有在项目最后构建的时候,合并多个模块文件,构建工具会自动生成模块名称

AMD规范本身也提供了对CJS规范的兼容,看下面以AMD规范定义的CJS兼容的代码.

define(function(require){
    var _ = require('underscore');
    var module = {
        // do stuff use _
    }
    return module;
});

上面的代码其实只是AMD规范的一个语法糖,最终会转变成下面的形式

define(['require','underscore'], function(require, _){
    var _ = require('underscore');
    var module = {
        // do stuff use _
    }
    return module;
});

回调函数的主体代码不会变,只是对它进行了包装,保证是以数组方式提供的依赖

但是这种语法有一个前提,require方法里的参数只能是字符串字面值,而不能是变量,或者有判断逻辑的加载,因为这种转换的原理是通过调用Function.prototype.toString,来转换的,所以不能解析变量或者逻辑,像下面的代码就是错误的

define(['require','underscore'], function(require, _){
    var reqName = 'underscore';
    var _ = require(reqName);
    /*
        or like this
        if (some){
            _ =require('abc');
        }else{
            _ = require('asdf');
        }
    */
    var module = {
        // do stuff use _
    }
    return module;
});

有哪些好用的AMD规范的实现呢?

目录
相关文章
|
4月前
|
JavaScript 前端开发 开发者
深入了解 AMD 和 CMD 规范:探索模块加载的世界(上)
深入了解 AMD 和 CMD 规范:探索模块加载的世界(上)
|
4月前
|
JavaScript 前端开发 开发工具
深入了解 AMD 和 CMD 规范:探索模块加载的世界(下)
深入了解 AMD 和 CMD 规范:探索模块加载的世界(下)
|
9月前
|
JavaScript API
说说AMD、CMD、commonJS模块化规范的区别?
说说AMD、CMD、commonJS模块化规范的区别?
107 0
|
9月前
|
JavaScript API
AMD、CMD、commonJS模块化规范的区别
AMD、CMD、commonJS模块化规范的区别
56 0
|
JavaScript 前端开发
使用基于 AMD 的 RequireJS 写一个花活项目
最近在研究前端模块化,大多数文章都提到了 AMD,关于 AMD 的模块标准(或者说规范)将的都很清楚,什么异步加载、保证正确顺序,对付八股很够,但是唯独没有关于 AMD 的实操工程,大多数是纸上谈
|
Linux Windows
OpenJDK8 u292刚刚发布,我司已经编译成功AMD64/MIPS64
OpenJDK8 u292刚刚发布,我司已经编译成功AMD64/MIPS64
170 0
|
Linux 虚拟化 Windows
AMD EPYC服务器OS兼容注意事项
单路平台上AMD EPYC的I/O优势更大一些,比如R7415也支持24个NVMe SSD。另外R7425的PCIe Riser选项为 “多达8个第3代插槽,多达6条x16通道”...
2173 0
|
JavaScript 前端开发 程序员
JavaSript模块规范--AMD规范与CMD规范
有了模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载什么模块;但是,这样做有一个前提,那就是大家必须以同样的方式编写模块,否则岂不是乱了套;考虑到Javascript模块现在还没有官方规范,这一点就更重要了
2337 0