JS的模块化是很常见的一个需求,在日常的开发过程中经常会用到,但是今天了解完这个知识点,才算是彻底明白了为什么要那样实现,真是醍醐灌顶,受益匪浅。
一 JS中的私有变量和特权方法
和其他语言不同,JS中没有私有,共有,类的概念。但是很特殊的一点,在JS的function中,有个私有变量的概念。比如下面的代码中,函数中有私有变量privateName和私有方法privateFunc,函数里面的变量和方法不能在函数外部被访问。
function functionName(){
var privateName = "name"; //私有变量
function privateFunc(){ //私有方法
console.log("privateFunc");
}
}
那如果我们想访问函数中的私有变量,要怎么办呢?
这个时候我们可以通过在函数里创建公有方法来访问本来不可以访问的私有变量和私有方法。我们把这个公有方法也叫特权方法。
有两种创建特权方法的方式。第一种是在构造函数中定义特权方法。基本的模式如下:
function FunctionName(){
var privateName = "name"; //私有变量
function privateFunc(){ //私有方法
console.log(privateName);
console.log("privateFunc");
}
this.getPrivateInfo = function(){
privateName = "I'm out";
return privateFunc();
}
}
我们运行一下上面的代码,发现在外部也可以访问私有变量了。因为在构造函数中,这个特权方法是一个闭包,所以可以访问它的包含函数中的变量。如果你对闭包还不是很了解,请先移步这里进行闭包相关知识的学习详解JS中的闭包
下一篇会详细写一下JS中构造函数的相关知识,如果你还不懂这里this为什么是这样,敬请期待下一篇有关构造函数的文章。
第二种创建特权方法的方式是使用静态私有变量,基本模式如下
(function(){
var privatename = "name";
function privateFunc(){
console.log("privateFunc")
}
MyObject = function(){} //注意这里没有用var,所以MyObject是全局变量
MyObject.prototype.getPrivateInfo = function(){
privateName = "I'm out";
return privateFunc();
}
})();
在上面的视线中,我们声明了一个全局变量MyObject,然后再实现一个闭包,和第一种方法原理相同,闭包可以访问包含函数的变量和方法。
两种方式的比较和权衡,构造函数方式对每个实例都要声明一个相同的方法,静态私有变量只声明一次,但是因为使用了原型,会对查询速度有一定的影响,两种方式根据实际情况灵活选择。
二 JS的模块模式
JS中的单例指的是只有一个实例的对象,在JavaScript中用创建对象字面量的方式创建单例。模式如下:
var sington = {
name:value,
method:function(){
//some code
}
}
对象字面量的sington变量是一个全局变量,所以在多人开发的过程中,可以看做独立的模块,所以是一个对象字面量是一个单例。
上面对象字面量的模式存在一个问题,这个里面的所有变量和方法都可以被其他模块访问,很不安全。所以模块模式通过为单例增加私有变量和特权方法使它增强。就是我想让其他模块访问的给暴露出去,不想被看到的就隐藏起来。实现方式如下:
var sington = function(){
var name = value;
function method(){
//some code
}
return {
publicProperty:true,
publicInfo:function(){
name += "zhangsan";
return method()
}
}
}();
这种模块模式还有一种增强的写法,就是在返回的单例必须是特定类型的实例,并且必须添加某些属性或方法。
var sington = function(){
var name = value;
function method(){
//some code
}
var obj = new Object();
obj.publicProperty = true;
obj.publicInfo = function(){
name += "zhangsan";
return method()
}
return obj;
}
}();
以上就是原生的JS实现模块化的方法,在ES6里新增了类的概念,而且也有很多AMD和CMD的写法。模块化始终是开发中的重点,了解原理对之后各种框架的理解也就深刻了。后续如果对于模块化有新的感想,也会不定期补充。