解析JavaScript中的“模块”模式

许多编程语言都有隐藏例如类的方法和属性的机制。 JavaScript没有内置工具可以毫不费力地实现这种效果。 但是,可以使用其他语言功能来模仿此类内容。

图片

该材料(我们今天发布的翻译版)专用于对“模块”设计模式的分析,该模式可让您将私人信息隐藏在错误中,仅使开发者决定公开。 本文主要针对初学者-适用于似乎熟悉闭包和IIFE之类的人,但尚未非常自信地使用它们的人。

国际教育展


您可以使用“模块”模式来控制JavaScript中变量的范围。 为了创建私有作用域,可以使用闭包。 如您所知,函数创建自己的范围,其内容与全局范围分开:

(function () { //      })(); 

我们面前有所谓的自调用函数( IIFE ,即刻调用函数表达式,即刻称为函数表达式)。 此函数在声明后立即执行。 使用此类功能来解决某个仅需解决一次的问题是很方便的,而不会在全局范围内留下任何多余的内容。 在此函数内部(以及其他函数内部),创建了一个私有作用域,该作用域无法从外部访问。 也就是说,如果在此范围内声明了另一个函数,则在执行IIFE之后,将无法对其进行访问。

 (function () { var myFunction = function () {   //     }; })(); 

现在,让我们尝试从程序的主要文本访问myFunction函数:

 myFunction(); // Uncaught ReferenceError: myFunction is not defined 

如您所见,正如预期的那样,此调用导致错误。 这告诉我们该功能在尝试访问它的范围内不可用。 实际上,在上面的两个示例中没有做任何有用的事情。 我们仅需要这些示例即可为分析“模块”模式做准备。

从IIFE和API模块返回对象


如何确保在另一个函数内部声明的函数仍然可以访问? 实际上,我们现在要谈论的是“模块”模式。 考虑以下示例。

 //   var Module = (function () { return {   myMethod: function () {     console.log('myMethod has been called.');   } }; })(); //      Module.myMethod(); 

您可能会注意到这里使用了与以前相同的IIFE,但是现在从函数中返回了带有方法的对象,可以从全局范围访问该对象。 自然,不能调用此方法。 应该注意的是,在这个例子中我们不使用闭包功能,我们将在下面讨论。

从IIFE返回的对象是普通对象,可以具有许多方法和属性。 它们形成一个公共接口或模块API。

 //   var Module = (function () { return {   myMethod: function () {   },   someOtherMethod: function () {   } }; })(); //      Module.myMethod(); Module.someOtherMethod(); 

私有变量和函数存储在闭包中


现在该讨论私有变量和函数了。 例如,某些辅助功能可以确保模块内部机制的运行。

这些可以是临时变量,也可以是起到某些数据存储作用的变量,我们希望对其进行严格控制。 我们对这种设备模块很感兴趣,因为只有外部设备可以使用,而其他所有东西都被隐藏了。 实际上,在我们的示例中,将从IIFE返回的对象之外声明的所有内容都将变为私有。

 var Module = (function () { var privateMethod = function () { }; return {   publicMethod: function () {   } }; })(); 

可以从外部调用此示例中的publicMethod方法,但是由于privateMethod功能处于私有范围内,因此无法在闭包中调用。 正是这种从外部无法访问的功能可以发挥模块辅助机构的作用。 它们可用于管理内部数据结构,对某些服务进行某些调用以及在其他情况下使用。

使用此类函数时,您需要考虑可以从同一作用域中声明的其他函数(包括从IIFE返回的对象的方法,甚至在return命令返回该对象之后)访问它们。 。 也就是说,公共方法可以访问私有功能,可以与它们交互,但是在全局范围内,这些私有功能不可用。

 var Module = (function () { var privateMethod = function () { }; return {   publicMethod: function () {     //       privateMethod,      :     // privateMethod();   } }; })(); 

因此,我们可以保护代码免受未经授权的干扰,并保护全球范围不受污染。 如果不这样做,则一方面,由于外部代码引用了不应访问的函数或变量,因此模块的内部机制的操作可能会意外或故意中断。 另一方面,如果不使用此处描述的方法,则很多不必要的事情都会落入全局范围,例如,这可能导致名称冲突。

这是从IIFE返回的对象的示例,该对象包含公共方法并且可以访问私有函数:

 var Module = (function () { var myModule = {}; var privateMethod = function () { }; myModule.publicMethod = function () { }; myModule.anotherPublicMethod = function () { }; return myModule; //      })(); //   Module.publicMethod(); 

命名私人和公共功能


有一个协议,根据该协议,私有功能名称的开头应加下划线。 仅通过查看代码,就可以了解哪些功能是内部的,哪些功能是公开可用的。 例如,它可能看起来像这样:

 var Module = (function () { var _privateMethod = function () { }; var publicMethod = function () { }; return {   publicMethod: publicMethod, } })(); 

总结


在本文中,我们研究了一种简单的“模块”模式,该模式通过使用由立即调用的函数表达式形成并从对象表达式返回的闭包,可以创建无法从外部直接操作的公共方法,私有函数和数据结构。 使用此模板,您可以隐藏模块的实现详细信息,防止它们被意外更改或有意更改,并有助于保持全局范围的整洁。

亲爱的读者们! 您是否在JS项目中使用“模块”模式?

Source: https://habr.com/ru/post/zh-CN419997/


All Articles