JS模块规范:AMD、UMD、CMD、commonJS、ES6 module

CommonJS

  • 特点:
    1、模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存。
    2、模块加载会阻塞接下来代码的执行,需要等到模块加载完成才能继续执行——同步加载。
  • 环境:服务器环境
  • 应用:nodejs的模块规范是参照commonJS实现的。
  • 语法:
    1、导入:require(‘路径’)
    2、导出:module.exports和exports

注意:module.exports和exports的的区别是exports只是对module.exports的一个引用,相当于Node为每个模块提供一个exports变量,指向module.exports。这等同在每个模块头部,有一行var exports = module.exports;这样的命令。

Demo

// 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

AMD

  • 特点:
    1、异步加载
    2、管理模块之间的依赖性,便于代码的编写和维护。
  • 环境:浏览器环境
  • 应用:requireJS是参照AMD规范实现的
  • 语法:
    1、导入:require([‘模块名称’], function (‘模块变量引用’){// 代码});
    2、导出:define(function (){return ‘值’);

Demo

// a.js
define(function (){
  return {
   a:'hello world'
  }
});
// b.js
require(['./a.js'], function (moduleA){
    console.log(moduleA.a); // 打印出:hello world
});

CMD

  • 特点
    1、CMD是在AMD基础上改进的一种规范,和AMD不同在于对依赖模块的执行时机处理不同,CMD是就近依赖,而AMD是前置依赖。
  • 环境:浏览器环境
  • 应用:seajs是参照CMD规范实现的,requireJS的最新的几个版本也是部分参照了CMD规范的实现
  • 语法:
    1、导入:define(function(require, exports, module) {});
    2、导出:define(function (){return ‘值’);

Demo

// a.js
define(function (require, exports, module){
  exports.a = 'hello world';
});
// b.js
define(function (require, exports, module){
    var moduleA = require('./a.js');
    console.log(moduleA.a); // 打印出:hello world
});

UMD

  • 特点:
    1、兼容AMD和commonJS规范的同时,还兼容全局引用的方式

  • 环境:浏览器或服务器环境

  • 应用:无

  • 语法:
    1、 无导入导出规范,只有如下的一个常规写法:

  • 常规写法:

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

ES6 module

  • 特点:
    1、按需加载(编译时加载
    2、import和export命令只能在模块的顶层,不能在代码块之中(如:if语句中),所以后来才出现了import()函数引入方式,它可以在代码块中实现异步动态按需动态加载,它返回的是一个promise对象
  • 环境:浏览器或服务器环境(以后可能支持)
  • 应用:ES6的最新语法支持规范
  • 语法:
    1、导入:import {模块名A,模块名B…} from ‘模块路径’
    2、导出:export和export default
    3、import(‘模块路径’).then()方法,这个类似于nodejs中的require()的方式,只不过,import()函数方式是异步的,require()是同步的

注意:export只支持对象形式导出,不支持值的导出,export default命令用于指定模块的默认输出,只支持值导出,但是只能指定一个,本质上它就是输出一个叫做default的变量或方法。

Demo

/*错误的写法*/
// 写法一
export 1;

// 写法二
var m = 1;
export m;

// 写法三
if (x === 2) {
  import MyModual from './myModual';
}

/*正确的三种写法*/
// 写法一
export var m = 1;

// 写法二
var m = 1;
export {m};

// 写法三
var n = 1;
export {n as m};

// 写法四
var n = 1;
export default n;

// 写法五
if (true) {
    import('./myModule.js')
    .then(({export1, export2}) => {
      // ...·
    });
}

// 写法六
Promise.all([
  import('./module1.js'),
  import('./module2.js'),
  import('./module3.js'),
])
.then(([module1, module2, module3]) => {
   ···
});

ES5 定义模块

用IIFE(立即执行函数)来定义一个模块,这样别的文件在引入该模块时就会自行执行,这种模块定义方式用在哪呢?主要是你想不经过编译就能直接使用的模块上,因为CommonJs和ES6都要经过编译后才能调用执行,就像你在自定义(手写)promise时,会自定义一个Promise.js模块文件,然后在同项目中调用该js文件使用,所以此时你可以用ES5的模块定义方式

//定义一个Promise.js文件模块
(function(window){     //函数形参接受传入的window对象
	function Promise(){   //定义模块内容
		内容。。。
	}
	window.Promise=Promise    //将内部定义函数(模块)暴露给全局,这样外界就可以使用了
})(window)   //将window对象传入IIFE函数中
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值