js模块化总结

前言

目前流行的js模块化规范有CommonJS、AMD、CMD以及ES6的模块系统

三种常见的js模块化规范

1:CommonJS

    伴随着NodeJS的兴起,能让JS在任何地方运行,特别是服务端,也达到了具备开发大型项目的能力,所以CommonJS营运而生。Node.jscommonJS规范的主要实践者。
    commonJS用同步的方式加载模块。在服务端,模块文件都存在本地磁盘,读取非常快,所以这样做不会有问题。但是在浏览器端,限于网络原因,更合理的方案是使用异步加载。

(1):规范

  1. 一个文件就是一个模块,拥有单独的作用域
  2. 普通方式定义的变量、函数、对象都属于该模块内
  3. 通过require来加载模块
  4. 通过exportsmodule.exports来暴露块中的内容

(2):注意

  1. exportsmodule.exports同时存在时,module.exports会覆盖exports
  2. 当模块内全是exports时,就等同于module.exports
  3. exports就是module.exports的子集
  4. 所有代码都运行在模块作用域,不会污染全局作用域
  5. 模块可以多次加载,但只会在第一次加载时候运行,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果
  6. 模块加载顺序,按照代码出现的顺序同步加载

(3):使用

暴露模块:

// 1:使用module.exports = value向外暴露一个对象
module.exports = {
  foo() {
    console.log('moudle1 foo()')
  }
}

// 2:使用module.exports = value向外暴露一个函数
exports.foo = function () {
  console.log('module3 foo()')
}

引入模块:

var module = require(模块名或模块路径)

// 例如:
//引用模块
let module1 = require('./modules/module1')
let module2 = require('./modules/module2')

//使用模块
module1.foo()
module2()

2:AMD

    Asynchronous Module Definition,异步加载模块。它是一个在浏览器端模块化开发的规范,不是原生js的规范,使用AMD规范进行页面开发需要用到对应的函数库,RequireJS

    AMD规范采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。

    使用require.js实现AMD规范的模块化:用require.config()指定引用路径等,用define()定义模块,用require()加载模块。

(1):使用

定义没有依赖的模块(dataService.js

define(function () {
  let msg = 'atguigu.com'

  function getMsg() {
    return msg.toUpperCase()
  }

  return {getMsg}
})

定义有依赖的模块(alerter.js

define(['dataService', 'jquery'], function (dataService, $) {
  let name = 'Tom2'

  function showMsg() {
    $('body').css('background', 'gray')
    alert(dataService.getMsg() + ', ' + name)
  }

  return {showMsg}
})

引入模块

(function () {
  //配置
  require.config({
    //基本路径
    baseUrl: 'js/',
    //映射: 模块标识名: 路径
    paths: {
      //自定义模块
      'alerter': 'modules/alerter',
      'dataService': 'modules/dataService',

      //库模块
      'jquery': 'libs/jquery-1.10.1',
      'angular': 'libs/angular'
      
    },

    //配置不兼容AMD的模块
    shim: {
      angular: {
        exports: 'angular'
      }

    }
  })

  //引入模块使用
  require(['alerter', 'angular'], function (alerter, angular) {
    alerter.showMsg()
    console.log(angular);
  })
})()

html引入main.js

<!DOCTYPE html>
<html>
<head>
    <title>Modular Demo 2</title>
</head>
<body>
    <script type="text/javascript" src="js/libs/require.js" data-main="js/main.js"></script>
 </body>
</html>

(2):主要解决的问题

  1. 文件可能有依赖关系,被依赖的文件需要早于依赖它的文件加载到浏览器
  2. js加载的时候浏览器会停止页面渲染,加载文件愈多,页面相应事件就越长
  3. 异步前置加载

3:ES6

ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,旨在成为浏览器和服务器通用的模块解决方案。其模块功能主要由两个命令构成:exportimportexport命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。

其实ES6还提供了export default命令,为模块指定默认输出,对应的import语句不需要使用大括号。这也更趋近于AMD的引用写法。

ES6的模块不是对象,import命令会被 JavaScript 引擎静态分析,在编译时就引入模块代码,而不是在代码运行时加载,所以无法实现条件加载。也正因为这个,使得静态分析成为可能。

(1):使用

export可以导出的是一个对象中包含的多个属性、方法。export default只能导出一个可以不具名的函数。我们可以通过import进行引用。同时,我们也可以直接使用require使用,原因是webpack起了server相关。

暴露模块:

// 用export一个个暴露
// 暴露函数 
export function foo() {
  console.log('module1 foo()');
}
// 暴露函数对象
export let bar = function () {
  console.log('module1 bar()');
}
// 暴露数组
export const DATA_ARR = [1, 3, 5, 1]


// 用export一起暴露
function fun1() {
  console.log('module2 fun1() ' + data);
}
function fun2() {
  console.log('module2 fun2() ' + data);
}
export {fun1, fun2}


// export default
export default {
  name: 'Tom',
  setName: function (name) {
    this.name = name
  }
}

2.import
import {fn} from ‘./xxx/xxx’ ( export 导出方式的 引用方式 )
import fn from ‘./xxx/xxx1’ ( export default 导出方式的 引用方式 )

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值