您当前的位置:首页 > 互联网教程

js的模块化编程有哪些方式

发布时间:2025-05-19 10:35:02    发布人:远客网络

js的模块化编程有哪些方式

一、js的模块化编程有哪些方式

1、我们首先简单地概述一下,自从三年前Eric Miraglia(YUI的开发者)第一次发表博客描述模块化模式以来的一些模块化模式。如果你已经对于这些模块化模式非常熟悉了,大可以直接跳过本节,从“进阶模式”开始阅读。

2、这是一种让一切变为可能的基本结构,同时它也是Javascript最棒的特性。我们将简单地创建一个匿名函数并立即执行它。所有的代码将跑在这个函数内,生存在一个提供私有化的闭包中,它足以使得这些闭包中的变量能够贯穿我们的应用的整个生命周期。

3、//... all vars and functions are in this scope only

4、// still maintains access to all globals

5、注意这对包裹匿名函数的最外层括号。因为Javascript的语言特性,这对括号是必须的。在js中由关键词function开头的语句总是会被认为是函数声明式。把这段代码包裹在括号中就可以让解释器知道这是个函数表达式。

6、Javascript有一个特性叫做隐式全局变量。无论一个变量名在哪儿被用到了,解释器会根据作用域链来反向找到这个变量的var声明语句。如果没有找到var声明语句,那么这个变量就会被视为全局变量。如果这个变量用在一句赋值语句中,同时这个变量又不存在时,就会创建出一个全局变量。这意味着在匿名闭包中使用或创建全局变量是很容易的。不幸的是,这会导致写出的代码极难维护,因为对于人的直观感受来说,一眼根本分不清那些是全局的变量。

7、幸运的是,我们的匿名函数提供了简单的变通方法。只要将全局变量作为参数传递到我们的匿名函数中,就可以得到比隐式全局变量更清晰又快速的代码了。下面是示例:

8、// now have access to globals jQuery(as$) and YAHOO in this code

9、有时你不仅想要使用全局变量,你还想要声明它们,以供反复使用。我们可以很容易地通过导出它们来做到这一点——通过匿名函数的返回值。这样做将会完成一个基本的模块化模式雏形,接下来会是一个完整的例子:

10、注意我们已经声明了一个叫做MODULE的全局模块,它拥有2个公有的属性:一个叫做MODULE.moduleMethod的方法和一个叫做MODULE.moduleProperty的变量。另外,它还维护了一个利用匿名函数闭包的、私有的内置状态。同时,我们可以很容易地导入需要的全局变量,并像之前我们所学到的那样来使用这个模块化模式。

11、上面一节所描述的基础已经足以应对许多情况,现在我们可以将这个模块化模式进一步的发展,创建更多强大的、可扩展的结构。让我们从MODULE模块开始,一一介绍这些进阶模式。

12、整个模块必须在一个文件中是模块化模式的一个限制。任何一个参与大型项目的人都会明白将js拆分多个文件的价值。幸运的是,我们拥有一个很棒的实现来放大模块。首先,我们导入一个模块,并为它添加属性,最后再导出它。下面是一个例子——从原本的MODULE中放大它:

13、 my.anotherMethod= function(){

14、我们用var关键词来保证一致性,虽然它在此处不是必须的。在这段代码执行完之后,我们的模块就已经拥有了一个新的、叫做MODULE.anotherMethod的公有方法。这个放大文件也会维护它自己的私有内置状态和导入的对象。

15、我们的上面例子需要我们的初始化模块最先被执行,然后放大模块才能执行,当然有时这可能也不一定是必需的。Javascript应用可以做到的、用来提升性能的、最棒的事之一就是异步执行脚本。我们可以创建灵活的多部分模块并通过宽放大模式使它们可以以任意顺序加载。每一个文件都需要按下面的结构组织:

16、在这个模式中,var表达式使必需的。注意如果MODULE还未初始化过,这句导入语句会创建MODULE。这意味着你可以用一个像LABjs的工具来并行加载你所有的模块文件,而不会被阻塞。

17、宽放大模式非常不错,但它也会给你的模块带来一些限制。最重要的是,你不能安全地覆盖模块的属性。你也无法在初始化的时候,使用其他文件中的属性(但你可以在运行的时候用)。紧放大模式包含了一个加载的顺序序列,并且允许覆盖属性。这儿是一个简单的例子(放大我们的原始MODULE):

18、 var old_moduleMethod= my.moduleMethod;

19、// method override, has access to old through old_moduleMethod...

20、我们在上面的例子中覆盖了MODULE.moduleMethod的实现,但在需要的时候,可以维护一个对原来方法的引用。

21、var MODULE_TWO=(function(old){

22、 var super_moduleMethod= old.moduleMethod;

23、// override method on the clone, access to super through super_moduleMethod

24、这个模式可能是最缺乏灵活性的一种选择了。它确实使得代码显得很整洁,但那是用灵活性的代价换来的。正如我上面写的这段代码,如果某个属性是对象或者函数,它将不会被复制,而是会成为这个对象或函数的第二个引用。修改了其中的某一个就会同时修改另一个(译者注:因为它们根本就是一个啊!)。这可以通过递归克隆过程来解决这个对象克隆问题,但函数克隆可能无法解决,也许用eval可以解决吧。因此,我在这篇文章中讲述这个方法仅仅是考虑到文章的完整性。

25、把一个模块分到多个文件中有一个重大的限制:每一个文件都维护了各自的私有变量,并且无法访问到其他文件的私有变量。但这个问题是可以解决的。这里有一个维护跨文件私有变量的、宽放大模块的例子:

26、 var _private= my._private= my._private||{},

27、 _seal= my._seal= my._seal|| function(){

28、 _unseal= my._unseal= my._unseal|| function(){

29、// permanent access to _private, _seal, and _unseal

30、所有文件可以在它们各自的_private变量上设置属性,并且它理解可以被其他文件访问。一旦这个模块加载完成,应用程序可以调用MODULE._seal()来防止外部对内部_private的调用。如果这个模块需要被重新放大,在任何一个文件中的内部方法可以在加载新的文件前调用_unseal(),并在新文件执行好以后再次调用_seal()。我如今在工作中使用这种模式,而且我在其他地方还没有见过这种方法。我觉得这是一种非常有用的模式,很值得就这个模式本身写一篇文章。

31、我们的最后一种进阶模式是显而易见最简单的。创建子模块有许多优秀的实例。这就像是创建一般的模块一样:

32、虽然这看上去很简单,但我觉得还是值得在这里提一提。子模块拥有一切一般模块的进阶优势,包括了放大模式和私有化状态。

二、requirejs模块化编程怎么理解

目前,通行的Javascript模块规范共有两种:CommonJS和AMD。

2009年,美国程序员Ryan Dahl创造了node.js项目,将javascript语言用于服务器端编程,这标志”Javascript模块化编程”正式诞生。

在浏览器环境下,没有模块也不是特别大的问题,毕竟网页程序的复杂性有限;但是在服务器端,一定要有模块,与操作系统和其他应用程序互动,否则根本没法编程。

node.js的模块系统,就是参照CommonJS规范实现的。在CommonJS中,有一个全局性方法require(),用于加载模块。

假定有一个数学模块math.js,就可以像下面这样加载。

var math= require('math');

然后,就可以调用模块提供的方法:

var math= require('math');

因为这个系列主要针对浏览器编程,不涉及node.js,所以对CommonJS就不多做介绍了。我们在这里只要知道,require()用于加载模块就行了。

AMD是”Asynchronous Module Definition”的缩写,意思就是”异步模块定义”。它采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。

define(id?, dependencies?, factory);

dependencies:所依赖的模块,可以省略。

factory:模块的实现,或者一个JavaScript对象。

AMD也采用require()语句加载模块,但是不同于CommonJS,它要求两个参数:

第一个参数[module],是一个数组,里面的成员就是要加载的模块;第二个参数callback,则是加载成功之后的回调函数。如果将前面的代码改写成AMD形式,就是下面这样:

require(['math'], function(math){

math.add()与math模块加载不是同步的,浏览器不会发生假死。所以很显然,AMD比较适合浏览器环境。

目前,主要有两个Javascript库实现了AMD规范:require.js和curl.js。本系列的第三部分,将通过介绍require.js,进一步讲解AMD的用法,以及如何将模块化编程投入实战。

require.js加载的模块,采用AMD(异步模块定义规范)规范。也就是说,模块必须按照AMD的规定来写。

1、实现js文件的异步加载,避免网页失去响应

2、管理模块之间的依赖性,便于代码的编写和维护

<script src="js/require.js" data-main="js/main"></script>

data-main属性的作用是,指定网页程序的主模块。在上例中,就是js目录下面的main.js,这个文件会第一个被require.js加载。由于require.js默认的文件后缀名是js,所以可以把main.js简写成main。

require(['moduleA','moduleB','moduleC'], function(moduleA, moduleB, moduleC){

require.config用来配置一些参数,它将影响到requirejs库的一些行为。

require.config的参数是一个JS对象,常用的配置有baseUrl,paths等。

这里配置了paths参数,使用模块名“jquery”,其实际文件路径jquery-1.7.2.js(后缀.js可以省略)。

我们知道jQuery从1.7后开始支持AMD规范,即如果jQuery作为一个AMD模块运行时,它的模块名是“jquery”。注意“jquery”是固定的,不能写“jQuery”或其它。

注:如果文件名“jquery-1.7.2.js”改为“jquery.js”就不必配置paths参数了。

如果将jQuery应用在模块化开发时,其实可以不使用全局的,即可以不暴露出来。需要用到jQuery时使用require函数即可。

require()函数接受两个参数。第一个参数是一个数组,表示所依赖的模块,上例就是['moduleA','moduleB',

'moduleC'],即主模块依赖这三个模块;第二个参数是一个回调函数,当前面指定的模块都加载成功后,它将被调用。加载的模块会以参数形式传入该函数,从而在回调函数内部就可以使用这些模块。

三、模块化什么意思

问题一:模块化是什么意思?模块化是一种处理复杂系统分解为更好的可管理模块的方式。

当前,实现模块化本体主要有两种主要的语言途径:一种是基于非经典语义的逻辑语言扩展,如分布式描述逻辑,E-连接和基于包的描述逻辑;另外一种途径是基于经典描述逻辑语义,但限制对外部符号的使用以保证各模块可安全的合并。

问题二:什么叫模块化结构?就是每个功能编程一个模块,简单的说就是一个子程序。只要表明入口出口就行了。这样别人用时很方便

问题三:路由器分模块化和非模块化是什么意思?模块化路由器就是有些功能可以根据客户的要求进行扩充,直接添加板卡就可以了

问题四:模块是什么意思? 20分在程序设计中,为完成某一功能所需的一段程序或子程序;或指能由编译程序、装配程序等处理的独立程序单位;或指大型软件系统的一部分。

问题五:枪械模块化是什么意思比如说现在还很火的SCAR,主要概念就是可能说我上战场,可以通过只更换部分主要零件来实现功能的变换,我现在打游击我可以用标准的5.56毫米标准枪管,可能突然我被调去当狙击手,我就换7.62的狙击长枪管,7.62的半自动发射机还有7.62的nato弹,装个两脚架加个光学瞄具就走了,过会让我当机枪手我就用自动的7.62发射机还有300米的白光瞄具就行,主要就是提高通用化,一个通用模块,一个突击模块,一个狙击模块,一个火力压制模块就可以了

问题六:数据化模块化是什么意思就是普通的24口网络配线架。模块化配线架是它的另一个叫法。

问题七:模块是什么意思,它跟函数有什么区别呀?就是把主函数分解掉,变成的模块,从主函数里一个一个模块的调用。

问题八:前端工程化和前端模块化是什么意思既然JavaScript不能handle如此大规模的代码,我们可以借鉴一下其它语言是怎么处理大规模程序设计的,在Java中有一个重要带概念――package,逻辑上相关的代码组织到同一个包内,包内是一个相对独立的王国,不用担心命名冲突什么的,那么外部如果使用呢?直接import对应的package即可

问题九:什么是模块化智能手机?模块化智能手机,即在一块主板上插入一些模块,使其成为一个手机。例如,如果需要更强性能的CPU,只要把低配置的CPU模块换下来,再插入高性能的CPU即可,还有摄像头,内存等同样可更换,这样升级手机就不必整机更换,只需更换某个模块即可,节约了成本,目前已经成型的模块化手机是Google公司的Project Ara,不过尚未上市。

问题十:模块化电源是什么意思模块化电源,比正常的电源要贵的多。但好处是明显的。在普通电源的机箱接线的地方,是一排接口。在你需要的时间把相对的接口插上就可以使用。在不需要时,就不插,这样可以节省机箱内的空间。