前端模块化雏形

■在网页开发的早期, js制作作为一种脚本语言, 只是yong'lai做-些简单的表单验证或动画实现等,那个时候代码还是很少的。

  • 那个时候的代码是直接写在<script>标签中。

■随着ajax异步请求的出现,慢慢形成了前后端的分离

  • 客户端需要完成的事情越来越多,代码量也是与日俱增。
  • 为了应对代码量的剧增,我们通常会将代码组织在多个js文件中, 进行维护。
  • 但是这种维护方式,依然不能避免一些灾难性的问题。

■比如全局变量同名问题

  • 开发人员甲在a.js文件中定义了一个变量flag值为true
  • 开发人员以在b.js文件中定义了一个变量也叫flag不过它的值为false

在某个页面引入了三个js文件

<script src="a.js" type="text/javascript" charset="utf-8"></script>
<script src="b.js" type="text/javascript" charset="utf-8"></script>
<script src="main.js" type="text/javascript" charset="utf-8"></script>

这时候开发人员甲想要在main.js文件中通过flag进行一些判断,来完成后续的事情

if(flag){
    console.log("flag为真时执行");
}

甲发现代码不能正常运行,但他校验了自己的flag确实为true,原因就是乙在b.js中定义的flag将它的值修改为了false。

■另外,这种代码的编写方式对js文件的依赖顺序几乎是强制性的

  • 你想要在b.js文件中修改a.js中的变量或方法,那它就一定要在a.js之后引入。
  • 但是当js文件过多,比如有几十个的时候,弄清楚它们的顺序是一件比较费时的事情。
  • 而且即使你弄清楚顺序了,也不能避免,上面出现的这种尴尬问题的发生。

解决方案:将需要暴露到外面的变量,使用一个模块作为出口
■通过匿名函数返回变量的方式

var moduleA = (function(){
    var name = 'xiufan'
    var age = 22
    var flag = true

    function sum(num1,num2){
            return num1+num2
    }

    var obj = {}
    obj.flag = flag;
    obj.sum = sum

    return obj;
})()
  • 在js文件中将代码写在一个匿名函数中因为函数有作用域,所以每个js文件中的代码都是独立的。
  • 当我们希望在其他js文件或让其他人在别的js文件中修改某个变量或方法时
  • 使用一个对象,并将要修改的数据作为它的属性,之后在return出去
  • 代码中我们将flag变量以及sum方法保存在对象obj之中,return出去的对象保存在变量modeleA中

■但我们要在b.js文件中使用flag或sum时,只要通过moduleA就可以获取,moduleA就可以看作一个模块。

(function(){
    if(moduleA.flag){
        console.log(moduleA.sum(40,50))
    }
})()

以上是ES5的语法中某块最基础的封装。
而现在前端模块化已有了很多既有的规范和对应的实现方案。


CommonJs

■模块化有两个核心:

  • 导入
  • 导出

■CommonJs的导出

//a.js
var flag = true

function sum(num1,num2){
    return num1+num2
}

module.exports = {
    flag,
    sum
}

■CommonJs的导入

//b.js
var a = require("a.js");
var flag = a.flag;
var sun = a.sum;

//使用对象的解构赋值
var {flag,sum} = require("a.js");
var flag = a.flag;
var sun = a.sum;