在实现js的模块化之前,我们首先想一下为什么要实现模块化编程呢?实现模块化编程有什么好处呢?或者说实现模块化编程我们可以解决什么样子的问题呢?如果在看本篇博客之前你不懂js的作用域链,请务必先看js的作用域链原理:Javascript之作用域链
在一个Web网站开发过程中,肯定不是一个人单独完成的,是由多个人共同完成一个网站的开发,每个人负责几个js文件的编写,假设我们现在有一个项目由两个人开发,A负责a.js编写,B负责b.js的编写,其中a.js有一个函数叫做deal,B中也有一个函数叫做deal。如下图所示
a.js
function deal(){
return 1;
}
b.js
function deal(){
return 2;
}
当我们调用的时候肯定在主页面这样引用
<script src="a.js">script>
<script src="b.js">script>
注意:这里就出现了问题,我们在作用域链那里讲过,标签的下面为一级作用域,同时一级作用域是共享的,也就是说在一级作用域中出现了两个deal函数,那么我们调用deal函数时,返回0还是返回1呢?(后引入的js文件中的deal函数会把前面引入的js文件中的deal函数覆盖掉)这就造成了代码的不兼容性,这才是一个函数不兼容,当我们代码越来越多时,从代码中寻找bug也会是一个非常类的过程,所以实现js的模块化也是非常必要的(也就是控制js的作用域)
a.js
var moduleA = function(){
this._count = 0;
this.deal= function(){
return 0;
};
}
b.js
var moduleB = function(){
this._count = 0;
this.deal= function(){
return 1;
};
}
解释:利用函数我们创建了两个二级作用域,一个js文件只向外暴漏一个属性,这样就很好了控制了作用域,但是有一个缺点,假设我们的_conut是私有属性,那么var a=new moduleA();alert(a._count)
,即我可以访问私有属性
为了解决上面的缺点,即我们不希望外界访问类的私有属性,我们通过给函数添加返回值实现
a.js
var moduleA = function(){
this._count = 0;
this.deal= function(){
return 0;
};
return {
deal:this.deal
}
}
解释 : 此时var a=new moduleA();alert(a._count)
,这时候显示a._count未定义。但是这一种写法还是有缺点,比如,我想在我模块中使用jquery对象,那应该怎么办呢?
我们利用function的构造函数实现模块内调用全局对象
var moduleB = (function ($) {
this.$=$;
})($);
假设我们模块想要扩展方法,那么我们应该怎么实现呢?
var moduleA = (function (m){
m.talk= function () {
};
return m;
})(moduleA);
我们给moduleA动态添加了一个方法叫做talk
在上面我们提供了4种方法来实现js的模块化编程,但是还是存在很多问题,比如:
<script src="a.js">script>
<script src="b.js">script>
问题1:当我们加载js文件的时候,若文件过大,页面会出现假死现象
问题2 : 我们实现模块的方式都是我们自己想的,所以缺少一个规范,即大家必须要用同样的方式来写模块
这两个问题我们将在下一篇博客介绍,也就是我们的AMD规范