JavaScript前端模块化

178 阅读3分钟

JavaScript 模块化编程,已经成为一个迫切的需求。理想情况下,开发者只需要实现核心的业务逻辑,其他都可以加载别人已经写好的模块。

但是,JavaScript不是一种模块化编程语言,ES6才就开始支持”类”和”模块“。传统的做法就是利用对象实现模块的效果

1.基本的实现方法

模块是实现特地功能的一组属性和方法的封装

简答的做法就是把模块写成一个对象,所有的模块成员都放到这个对象里面。

var module1 = new Object({
    count:0,
    m1:function(){
        console.log('m1');
    },
    m2:function(){
        console.log('m1');
    }
})

上面的函数m1m2,都封装在module1对象里。使用的时候,就是调用这个对象的属性。

module1.m1();//"m1"   在需要的HTML页面调用

但是,这样的写法会暴露所有模块成员,内部状态可以被外部改写。比如,外部代码可以直接改变内部计数器的值。

module1.count = 10;

封装私有变量:立即执行函数的写法

另一种做法是使用“立即执行函数”(Immediately-Invoked Function Expression,IIFE),将相关的属性和方法封装在一个函数作用域里面,可以达到不暴露私有成员的目的。

var module1 = (function () {
 var count = 0;
 var m1 = function () {
   //...
 };
 var m2 = function () {
  //...
 };
 return {   //这个是属于module1的
  m1 : m1,
  m2 : m2
 };
})();

使用上面的写法,外部代码无法读取内部的count变量。

console.info(module1.count); //undefined   获取不到模块内部的count

上面的module1就是 JavaScript 模块的基本写法。

模块放大模式

如果一个模块很大,必须分成几个部分,或者一个模块需要继承另一个模块,这时就有必要采用“放大模式”。

JS模块代码

var module1=(function(){
	var count=0;
	var m1=function(){
		console.log('m1');
	};
	var m2=function(){
		console.log('m2');
	}
	return {
		m1: m1,
		m2: m2
	}
})();
(function(mod){
	mod.m3=function(){
		console.log('m3')
	}
	return mod;  //相当于把module1返回
})(module1);

HTML调用

<script src="js/module.js"></script>
	<script>
		
			module1.m1();
			module1.m2();
			console.log(module1)
	</script>

module1还有另一个方法m3,但是m3是属于另一个模块的,m3继承module1。有另一个函数,在里面挂载m3的方法,module1传入,mod接收。mod.m3挂载一个方法,把mod返回。

在浏览器环境中,模块的各个部分通常都是从网上获取的,有时无法知道哪个部分会先加载。如果采用上面的写法,第一个执行的部分有可能加载一个不存在空对象,这时就要采用”宽放大模式”(Loose augmentation)。

var module1 = (function (mod) {
 //...
 return mod;
})(window.module1 || {});

window.module1如果有值就把module1对象赋值给mod,最终返回,如果没有值那就给一个空对象,在空对象中加载m3

命名空间

在一个项目中可能会引入很多个JS文件,JS文件多了,那么JS模块也就增加。模块中声明变量的时候可能会存在冲突问题。那么我们就在自己的模块中造就命名空间,给当前变量对象造就自己的空间。