JS之AMD、CMD、CommonJS、ES6、UMD的使用笔记

前言

如下图:

AMD与CMD的主要区别:

  • 1. 对于依赖的模块,AMD 是提前执行,CMD 是延迟执行。不过 RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)。CMD 推崇 as lazy as possible.
  • 2. CMD 推崇依赖就近,AMD 推崇依赖前置。看代码:
// CMD
define(function(require,exports,module) {
    var a = require('./a')
    a.doSomething()
    var b = require('./b')
    b.doSomething()
})
 AMD 默认推荐的是
define(['./a','./b'],function(a,b) {  依赖必须一开始就写好  
    a.doSomething()
    b.doSomething()
})

AMD与CMD的其它区别可参考地址:https://www.zhihu.com/question/20351507

AMD

AMD规范可参考地址:https://github.com/amdjs/amdjs-api/wiki/AMD  

AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。

根据AMD规范,我们可以使用define定义模块,使用require调用模块,语法:

 define(id?,dependencies?,factory);
  • id: 定义中模块的名字;可选;如果没有提供该参数,模块的名字应该默认为模块加载器请求的指定脚本的名字;
  • dependencies:依赖的模块;
  • factory:工厂方法,返回定义模块的输出值。

总结一段话:声明模块的时候指定所有的依赖dependencies,并且还要当做形参传到factory中,对于依赖的模块提前执行,依赖前置

例子1:

 define("alpha",["require","exports","beta"],1)"> (require,beta) {
       exports.verb = () {
           return beta.verb();
           Or:
           return require("beta").verb();
       }
   });

例子2:

 define(["alpha"],1)"> (alpha) {
        {
         verb: (){
           return alpha.verb() + 2;
         }
       };
   });

例子3:

   define({
     add: (x,y){
       return x + y;
     }
   });

例子4:

define(var a = require('a'),b = require('b');

     exports.action =  () {};
   });

使用require函数加载模块:

require([dependencies],1)">function(){});
  • 第一个参数是一个数组,表示所依赖的模块
  • 第二个参数是一个回调函数,当前面指定的模块都加载成功后,它将被调用.加载的模块会以参数形式传入该函数,从而在回调函数内部就可以使用这些模块

require()函数在加载依赖的函数的时候是异步加载的,这样浏览器不会失去响应,它指定的回调函数,只有前面的模块都加载成功后,才会运行,解决了依赖性的问题

require(['alpha'],1)">(alpha){
    alpha.verb ();
})

CMD

CMD规范参考地址:https://github.com/seajs/seajs/issues/242  CMD 是 SeaJS 在推广过程中对模块定义的规范化产出。

define Function

define 是一个全局函数,用来定义模块。

define define(factory)

define 接受 factory 参数,factory 可以是一个函数,也可以是一个对象或字符串。

factory 为对象、字符串时,表示模块的接口就是该对象、字符串。比如可以如下定义一个 JSON 数据模块:

define({ "foo": "bar" });

也可以通过字符串定义模板模块:

define('I am a template. My name is {{name}}.');

factory 为函数时,表示是模块的构造方法。执行该构造方法,可以得到模块向外提供的接口。factory 方法在执行时,默认会传入三个参数:requireexports 和 module

define( 模块代码

});

define define(id?,deps?,factory)

define 也可以接受两个以上参数。字符串 id 表示模块标识,数组 deps 是模块依赖。比如:

define('hello',['jquery'],1)">
});

id 和 deps 参数可以省略。省略时,可以通过构建工具自动生成。

注意:带 id 和 deps 参数的 define 用法不属于 CMD 规范,而属于 Modules/Transport 规范。

define.cmd Object

一个空对象,可用来判定当前页面是否有 CMD 模块加载器:

if (typeof define === "function" && define.cmd) {
   有 Sea.js 等 CMD 模块加载器存在
}

 require Function

require 是 factory 函数的第一个参数。

require require(id)

require 是一个方法,接受 模块标识 作为唯一参数,用来获取其他模块提供的接口。

define( 获取模块 a 的接口
  );

   调用模块 a 的方法
  a.doSomething();

});

require.async require.async(id,callback?)

require.async 方法用来在模块内部异步加载模块,并在加载完成后执行指定回调。callback 参数可选。

define( 异步加载一个模块,在加载完成时,执行回调
  require.async('./b',1)">(b) {
    b.doSomething();
  });

   异步加载多个模块,在加载完成时,执行回调
  require.async(['./c','./d'],1)">(c,d) {
    c.doSomething();
    d.doSomething();
  });

});

注意:require 是同步往下执行,require.async 则是异步回调执行。require.async 一般用来加载可延迟异步加载的模块。

exports Object

exports 是一个对象,用来向外提供模块接口。

define( 对外提供 foo 属性
  exports.foo = 'bar';

   对外提供 doSomething 方法
  exports.doSomething = () {};

});

除了给 exports 对象增加成员,还可以使用 return 直接向外提供接口。

define((require) {

   通过 return 直接提供接口
   {
    foo: 'bar',doSomething: () {}
  };

});

module Object

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

module.id String

模块的唯一标识。

define('id',[],1)">
});

上面代码中,define 的第一个参数就是模块标识。

module.exports Object

当前模块对外提供的接口。

传给 factory 构造方法的 exports 参数是 module.exports 对象的一个引用。只通过 exports 参数来提供接口,有时无法满足开发者的所有需求。 比如当模块的接口是某个类的实例时,需要通过 module.exports 来实现:

define( exports 是 module.exports 的一个引用
  console.log(module.exports === exports);  true

   重新给 module.exports 赋值
  module.exports = new SomeClass();

   exports 不再等于 module.exports
  console.log(module.exports === exports);  false

});

CommonJS 

CommonJS是服务器端模块的规范,Node.js采用了这个规范.Node.JS首先采用了js模块化的概念.
CommonJS定义的模块分为:模块引用(require)/ 模块定义(exports)/模块标识(module)

所有代码都运行在模块作用域,不会污染全局作用域。

模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存。

模块加载的顺序,按照其在代码中出现的顺序。

common.js
module.exports = (a,b) {
return a-b
}

let minus = require('./common.js')  文件相对路径
console.log(minus(5,4)) 
 结果: 1

详细可以参考《阮一峰:CommonJS规范》

ES6

导出

ES6两种导出方式:

  1. 命名导出
  2. 默认导出

命名导出

 写法1
export const name = 'calculator';
export const add =  (a,b) {
    return a + b;
}

 写法2
const name = 'calculator';
const add =  b;
}
export {name,add};

在使用命名导出时,可以通过as关键字对变量重命名。如:

const name = 'calculator' 在导入时即为name 和 getSum

默认导出

export default {
    name: 'calculator';,add:  b;
    }
}; 

导入

针对命名导出的模块,导入方式如下:

 calculator.js
const name = 'calculator' 一般导入方式
import {name,add} from './calculator.js'
add(2,3);

 通过as关键字对导入的变量重命名
import {name,add as calculateSum} from './calculator.js'
calculateSum(2,1)"> 使用 import * as <myModule>可以把所有导入的变量作为属性值添加到<myModule>对象中,从而减少了对当前作用域的影响
import * as calculateObj from './calculator.js'
calculateObj.add(2,3);

对于默认导出来说,import后面直接跟变量名,并且这个名字可以自由指定,它指代了calculator.js中默认导出的值。从原理上可以这样理解:

import {default as myCalculator} from './calculator.js'

还有两种导入方式混合起来使用的例子,如下:

 index.js
import React,{Component} from 'react';

注:这里的React必须写在大括号前面,而不能顺序颠倒,否则会提示语法错误。

 复合写法

在工程中,有时候需要把一个模块导入后立即导出,比如专门用来集合所有页面或组件的入口文件。此时可以采用复合形式的写法:

export {name,add } from './calculator.js'

复合写法只支持通过命名导出的方式暴露出来的变量,默认导出则没有对应的复合形式,只能将导入和导出拆分开。

import calculator from './calculator.js'
export default calculator;

 UMD

UMD并不能说是一种模块标准,不如说它是一组模块形式的集合更准确。UMD的全称是Universal Module Definition,也就是通用模块标准。它的目标是使一个模块能运行在各种环境下,不论是CommonJS、AMD,还是非模块化的环境(当时ES6 Module还未被提出)

((root,factory) {
    typeof define === 'function' && define.amd) {
         AMD
        define(['jquery'],factory);
    } else typeof exports === 'object') {
         Node,CommonJS之类的
        module.exports = factory(require('jquery'));
    } else {
         浏览器全局变量(root 即 window)
        root.returnExports = factory(root.jQuery);
    }
}(this,1)">($) {
     方法
     myFunc() {};

     暴露公共方法
     myFunc;

}));

 详细可参考:《可能是最详细的UMD模块入门指南》《AMD,CMD,CommonJS,ES Module,UMD》

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


kindeditor4.x代码高亮功能默认使用的是prettify插件,prettify是Google提供的一款源代码语法高亮着色器,它提供一种简单的形式来着色HTML页面上的程序代码,实现方式如下: 首先在编辑器里面插入javascript代码: 确定后会在编辑器插入这样的代码: <pre
这一篇我将介绍如何让kindeditor4.x整合SyntaxHighlighter代码高亮,因为SyntaxHighlighter的应用非常广泛,所以将kindeditor默认的prettify替换为SyntaxHighlighter代码高亮插件 上一篇“让kindeditor显示高亮代码”中已经
js如何实现弹出form提交表单?(图文+视频)
js怎么获取复选框选中的值
js如何实现倒计时跳转页面
如何用js控制图片放大缩小
JS怎么获取当前时间戳
JS如何判断对象是否为数组
JS怎么获取图片当前宽高
JS对象如何转为json格式字符串
JS怎么获取图片原始宽高
怎么在click事件中调用多个js函数
js如何往数组中添加新元素
js如何拆分字符串
JS怎么对数组内元素进行求和
JS如何判断屏幕大小
js怎么解析json数据
js如何实时获取浏览器窗口大小
原生JS实现别踩白块小游戏(五)
原生JS实现别踩白块小游戏(一)