第一章、前端模块化之旅

一、CommJS

简介:
在JavaScript发展初期就是为了实现简单的页面交互逻辑,寥寥数语即可;如今CPU、浏览器性能得到了极大的提升,很多页面逻辑迁移到了客户端(表单验证等),随着web2.0时代的到来,Ajax技术得到广泛应用,jQuery等前端库层出不穷,前端代码日益膨胀,这时候JavaScript作为嵌入式的脚本语言的定位动摇了,JavaScript却没有为组织代码提供任何明显帮助,甚至没有类的概念,更不用说模块(module)了,JavaScript极其简单的代码组织规范不足以驾驭如此庞大规模的代码。
特点:

  1. CommJs是Node.js首先采用的js模块化方案,它是服务器端的模块加载方案。
  2. CommJs是模块,服务器端的所有模块都放在本地硬盘,等待模块时间就是硬盘读取文件时的时间,很小,但是对浏览器而言,它需要从服务器加载模块,涉及网速,代理等原因,所以同步加载不适合浏览器端。
  3. Node.js四个重要的环境变量:module、exports、require、global为CommJs的实现提供了支持。
  4. require()用来引入外部模块;exports对象用于导出当前模块的方法或变量,唯一的导出口;module对象就代表模块本身。
  5. npm是CommJs的包管理器,所以它也是遵循CommJs规范的。
  6. CommonJS 模块的顶层this指向当前模块。
  7. 根据CommonJS规范,一个单独的文件就是一个模块,每一个模块都是一个单独的作用域。除非定义为global的属性。
//  a.js
exports.fn = () => {console.log('fn')}  ===  module.exports.fn = () => {console.log('fn')}
或者  module.exports = {fn: () => { console.log('fn')}}

//  index.js
var test = require(./a.js)
test.fn()
//  fn

二、AMD

AMD 即Asynchronous Module Definition,中文名是的意思。它是一个在浏览器端模块化开发的规范,由于不是JavaScript原生支持,使用AMD规范进行页面开发需要用到对应的库函数,也就是,实际上AMD 是 RequireJS 在推广过程中对模块定义的规范化的产出。
特点

  1. 异步加载模块。它指定的回调,只有当所有模块都被加载成功后,才会运行,避免了网页失去响应。
  2. :在解析和执行当前模块之前,模块作者就必须指明当前模块所依赖的模块。
require(['./a','./b'],function(a,b){
   a.doSomething()
   b.doSomething()
})
  1. 性能好(比较CMD(SeaJs)):代码运行到此处就知道依赖的所有模块。
  2. 管理模块之间的依赖性,便于代码的编写和维护。

文件路径

  • index.html
  • js
    • main.js
    • other
      • moduleA.js
      • moduleB.js
        ......

//  1. 引入RequireJs(index.html)
//  async属性表明这个文件需要异步加载,避免网页失去响应。IE不支持这个属性,只支持defer,所以把defer也写上。
//  2. data-main属性指定网页程序的主模块


//  3. 主模块main.js的写法
//  所有模块加载完后才执行
require(["other/moudleA","other/moudleB","other/moduleC","other/jquery"], function(moduleA,moudleB,moduleC,$){
    //  your code......
}) 

三、CMD

CMD(Common Module Definition)规范是国内发展起来的,中文名是通用模块定义,它需要用到的库函数就是SeaJs。
特点

  1. 异步加载
  2. :可以把你依赖写到代码中的任何地方
define(function(require, exports, module) {
  var a = require('./a')
  a.doSomething()
  var b = require('./b')
  b.doSomething()
})
  1. 性能差(比较AMD(RequireJs)),但是使用方便

总结AMD和CMD:
AMD开始就定义了所有模块,根据网络速度,哪个模块先下载好,哪个模块就执行,但是所有模块下载完成后才会执行require回调函数。
CMD开始不知道需要下载那些模块,因为reuqire在各文件的任何位置,所以遍历所有require的位置后,才开始下载所有模块,下载完后才依次执行reuqire的模块,所以消耗性能,但是执行循序和书写顺序是一致的。

简述:AMD、CMD 相对命比较短,到2014年就摇摇欲坠,因为Node.js和Browsersify的兴起,运行时异步加载逐渐被构建时模块化合并分块所替代,webpack已经成为前端必备神器。

四、ES6模块化(import/export)

这里主要讲ES6模块化和CommonJs原理上的区别

  1. CommonJs模块是值的拷贝:

    ES6模块是值的引用:
    \color{red}{JS引擎对脚本静态分析时就会生成引用,等脚本真正执行时,import拿到的是执行时的值,所以是动态引用。}
  2. CommonJS模块是运行时加载,ES6模块是编译时输出接口。
  3. CommonJs模块是浅拷贝,可以外部修改其值。ES6模块只能静态读取,不能修改其值。
  4. CommonJs模块是对象,模块内顶层this指向本模块的对象。ES6模块内的顶层this返回undefined。

你可能感兴趣的:(第一章、前端模块化之旅)