主要是指前端js的模块化。随着前端的发展,前端能够做的东西越来越多,越来越复杂,把所以的功能都写在同一个js文件中随着功能的复杂度增加,js文件的大小也会增加,全局变量污染,代码耦合度太高,不利于调试和排错等等,而模块化开发就能够解决这些问题。
什么是模块化,为什么要模块化,模块化的好处
这些都不说了,网上很多文章自己去了解一下。重点说一下如何进行模块化开发。
首先了解模块化开发的发展过程有助于理解模块化开发的思路。
模块化开发发展的过程
1、将不同的功能写在不同的块(文件)中,使用的时候将需要的功能模块引入html中。
//module1
function foo(){
...
}
function bar(){
...
}
//module2
function foo(){
...
}
从上面的代码中可以看见,两个模块中都包含了名为foo的方法。这里就有一个问题,如果这两个文件都引入,必然会有一个被另一个覆盖(那个被覆盖需要看具体的引入顺序)。污染全局变量,命名发生冲突。为了解决上面的问题就有了下面的解决办法。
2、使用命名空间
//module1
var module1 = {
foo:function(){},
bar:function(){}
}
//module2
var module2 = {
foo:function(){}
}
//使用的时候这样使用
module1.foo();
module2.foo();
上面的方法解决了全局变量污染导致命名冲突的问题,但是又有一个新问题,不够安全。对象属性可以被随意修改,比如:
//module1
var module1 = {
foo:function(){},
bar:function(){}
}
module1.foo = '我是一个字符串。'
console.log(typeof module1.foo) //string
3、使用 IIFE(立即执行函数)
使用立即执行的匿名函数只暴露部分方法,可以达到不暴露私有成员的目的。
var module1 = (function(){
var num = 1;
var add = function(){
num++;
console.log(count)
}
var minus = function(){
num--;
console.log(count)
}
var say = function(msg){
console.log(msg)
}
return {
add:add,
minus:minus,
say:say
}
})()
module1.num //undefined
假如我有一个模块需要使用module1中的say方法怎么办呢。
4、依赖引入
var module1 = (function(){
var say = function(msg){
console.log(msg)
}
return {
say:say
}
})()
var module2 = (function(m1){
var speak = function(msg){
m1.say(msg);
}
return {
speak:speak
}
})(module1)
module2.speak('Hello World!')
把依赖的模快或者其中的方法作为参数传给匿名执行函数即可。
到这里,模块化开发的雏形已经形成。但是还有一个问题需要解决的。如果依赖太多,需要引入的文件就会越多,浏览器需要发送的请求也会越多,而且引入的顺序不对的话程序就会报错,依赖模糊导致维护困难。
为了解决这些问题,接下来就需要说一下模块化开发的一些规范了,只有遵循一定的规范才能够开发出方便大家使用的模块。
模块化开发规范
目前常见的模块化开发规范有以下几种:CommonJs, AMD, CMD, ES6,如何使用,请看接下来的几篇文章。