JavaScript 中的模块和揭示模块模式






4.94/5 (8投票s)
用简单的语言解释 JavaScript 中的模块和揭示模块模式
这是关于 JavaScript 作用域管理的系列文章中的第二篇。在第一篇文章中,我详细讨论了立即调用的函数表达式 (IIFE)。如果你不熟悉 IIFE 并且还没有机会阅读前一篇文章,我建议你在继续阅读之前先阅读那一篇。
这篇文章将重点介绍 JavaScript 中的模块和揭示模块模式。当我们想到面向对象编程时,首先想到的是类。什么是类?简单来说,类是变量和方法的封装。类可以有public
(公共)和private
(私有)成员。根据你想向类外部公开哪些信息,你可以将相关的变量和方法设为public
,而将不应公开的内容设为private
。
JavaScript 是一种面向对象的语言。但 JavaScript 默认不支持private
变量和函数。然而,有一些方法可以在语言中实现相同的private
-public
结构。默认情况下,JavaScript 中的任何函数都分配有全局作用域。看下面的函数
function keepMePrivate() {
console.log("Let others not bother what I do!");
}
函数keepMePrivate
可以从任何地方调用,并且是全局可访问的。在某些情况下,你可能希望将一些函数(甚至变量)设为private
。这时模块模式就派上用场了。看看下面的代码
var module = (function() {
console.log("You have started learning about a Module");
}());
你一定还记得我们在上一篇文章中学到的 IIFE 模式。我声明了一个 IIFE,它向浏览器的控制台写入一个简单的消息。IIFE 创建了一个局部作用域,并将其中所有的变量和函数保持为private
。然后,我们只能将那些我们想要公开的变量和函数返回给外部世界。我将 IIFE 赋值给一个变量module。这样做,我创建了一个全局可访问的模块。但是,目前这个模块没什么用。它将逐渐演变成一些真实可用的东西。
var module = (function() {
var privateVar = "Stop thinking about me dear foreigners";
var privateFunc = function() {
console.log("You are now learning how to create private functions.");
};
}());
现在我们有一个变量privateVar
和一个函数privateFunc
,它们对于 IIFE 块来说是private
的。任何在外部尝试使用它们的行为都不是应受惩罚的罪过 :) 但肯定会抛出错误,导致你的 JavaScript 代码中断。我们的模块仍然无用,因为我们还没有从 IIFE 块返回任何东西。我们继续。
var module = (function() {
var privateFunc = function() {
console.log("I'm private. Only my family knows what I do.");
}
return {
publicVar: "Good things are available to good people.",
publicFunc: function() {
privateFunc();
console.log("Keep focused and learn to create public functions");
}
};
}());
我们已经达到了一个拥有工作模块的程度。上面的 IIFE 返回一个对象,其中publicVar
作为属性,publicFunc
作为方法。这就是所谓的创建对象的字面量表示法。你可以在我关于JavaScript 对象的文章中阅读更多关于对象字面量的信息。
返回的对象被赋值给变量module
。函数privateFunc
可以在publicFunc
内部访问。IIFE 外部的任何代码都不能直接调用privateFunc
。可以通过点号表示法调用返回对象的成员,如下所示
var someVar = module.publicVar;
module.publicFunc();
上面的 IIFE 返回一个匿名对象。还有其他方法可以实现相同的功能。下面这种方法称为命名局部对象字面量。
var module = (function() {
var privateFunc = function() {
console.log("I'm private. Only my family knows what I do.");
}
var myObj = {};
myObj.publicVar = "Good things are available to good people.";
myObj.publicFunc = function() {
privateFunc();
console.log("Keep focused and learn to create public functions");
}
return myObj;
}());
我们首先创建了一个空对象myObj
,然后稍后添加了属性publicVar
和方法publicFunc
。最后,我们返回命名对象myObj
。当你的模块中有大量代码时,并且你想清楚地看到哪些是public
成员,而无需查看return
语句时,这很有用。
下面展示了这个模式的一个小变体,我们在定义命名对象本身时,将所有public
成员放入对象中。最后,对象按惯例返回。
var module = (function() {
var myObj = {
publicVar: "Good things are available to good people.",
publicFunc: function() {
console.log("Keep focused and learn to create public functions");
}
};
return myObj;
}());
到目前为止我们看到的就是所谓的模块模式。它有一个改进版本,称为揭示模块模式。我们接下来看它。
揭示模块模式
揭示模块模式允许你以传统的 JavaScript 方式定义变量和函数,并在最后提供指定public
成员的机制。基本上,我们将所有属性和方法定义为具有private
模块级作用域,并返回一个匿名对象,其属性是指向private
成员的指针。请看下面的说明
var revealingModule = (function() {
var privateVar = "Keep me private";
var publicVar = "Return me as public";
function privateFunc() {
console.log("A private function");
}
function publicFunc1() {
console.log("First public function");
}
function publicFunc2() {
console.log("Second public function");
}
return {
publicProperty: publicVar,
firstPublicMethod: publicFunc1,
secondPublicMethod: publicFunc2
};
}());
这是一种非常简洁地指定你想向外部世界公开的public
成员的方法。该模式的主要优点是代码的可读性。你可以很容易地在return
语句中找出公开的变量和函数。你可以根据自己的喜好为返回对象的属性和方法命名。
当我们想在 JavaScript 中管理作用域时,模块和揭示模块模式非常有用。让我们通过另一个例子来理解这一点。
var rectangle = (function() {
function getArea(length, breadth) {
return length*breadth;
}
function getPerimeter(length, breadth) {
return 2*(length + breadth);
}
return {
GetArea: getArea,
GetPerimeter: getPerimeter
};
}());
我们正在创建一个名为rectangle
的模块,它有两个private
方法getArea
和getPerimeter
。这两个方法都应该是不言自明的。我们返回一个对象,其中包含两个属性GetArea
和GetPerimeter
,它们分别包含函数getArea
和getPerimeter
。包含函数的属性称为方法。我们可以使用变量rectangle
调用方法GetArea
和GetPerimeter
,如下所示。
var area = rectangle.GetArea(2, 3); // area = 6
var perimeter = rectangle.GetPerimeter(2, 3); // perimeter = 10
使用揭示模块模式为private
实现提供抽象。这就像向外部世界公开public
API,同时将实现细节保留为private
。
你喜欢这篇文章吗?请在评论框中留下你的评论、问题或建议,让我听到你的声音。感谢阅读。
热爱 JavaScript 并想进一步探索这门语言?请访问我的博客 www.code-morning.com