当前位置: 首页 > 科技观察

模块化你的JS代码

时间:2023-03-16 18:28:51 科技观察

为什么要使用模块模式?因为声明在全局范围内的变量和函数自动成为全局对象Window的属性,这往往会导致命名冲突和一些很重要的可能维护问题,全局变量越多,引入bug的概率就越大!因此,我们应该尽可能少地使用全局变量。模块化的目的之一就是解决这个问题!零全局变量模式该模式应用场景较少,通过一个IIFE(立即执行的匿名函数)将所有代码包裹起来,让所有的变量和函数都隐藏在函数内部,不会污染整个世界。使用场景:当代码不依赖其他代码时;当代码不需要在运行时不断扩展或修改时;当代码很短,不需要与其他代码交互时;单一全局变量模式的基本定义单一全局变量模式是只创建一个全局变量(或者创建尽可能少的全局变量),并且全局变量的名称必须是唯一的,并且不会与当前和以后的内置API,所有的函数代码都会挂载到这个全局变量上。它在各种流行的类库中被广泛使用,例如:YUI定义了唯一的YUI全局对象JQuery定义了两个全局对象$和JQueryDojo定义了一个dojo全局对象Closure定义了一个goog全局对象示例:varMymodule={};Mymodule.Book=function(){...};Mymodule.Book.prototype.getName=function(){....};Mymodule.Car=function(){...};Mymodule.Car.prototype.getWheels=function(){....};模块的定义模块是一个通用的函数片段,它不会创建新的全局变量或命名空间,而是将所有代码存储在一个单独的函数中,可以用一个名字来表示这个模块,这个模块也可以依赖在其他模块上。functionCoolModule(){varsomething='cool';varanother=[1,2,3];functiondoSomething(){console.log(something);}functiondoAnother(){console.log(another.join('!'));}return{doSomething:doSomething,doAnother:doAnother};}varfoo=CoolModule();foo.doSomething();//coolfoo.doAnother();//1!2!3这里的CoolModule是一个模块,不过它只是一个函数,这里调用了CoolModule函数创建了一个模块实例foo,此时形成了一个闭包(因为CoolModule返回的是一个对象,其中一个属性引用了一个内部函数),模块CoolModule返回的对象是模块的公共API(也可以直接返回一个内部函数)因此,模块模式需要满足两个必要条件:必须有一个外部关闭的函数,并且该函数必须至少被调用一次(每次调用都会创建一个新的模块实例),比如CoolModule的封闭函数必须至少返回一个内部函数,这样内部函数才能在私有范围内形成一个闭包,并且可以访问或修改私有状态单例模块模式实现:varfoo=(functionCoolModule(){...//代码是the同上例})();foo.doSomething();foo.doAnother();您还可以在模块内部保留对公共API对象的内部引用,以便您可以在内部修改模块实例,包括添加、删除方法和属性functionCoolModule(){varsomething='cool';varanother=[1,2,3];functionchange(){pubicAPI.doSomething=doAnother;}functiondoSomething(){console.log(something);}functiondoAnother(){console.log(another.join('!'));}varpubicAPI={change:change,做某事:做某事g};returnpublicAPI;}varfoo=CoolModule();foo.doSomething();//coolfoo.change();foo.doSomething();//1!2!3varfoo1=CoolModule();foo1.doSomething();//cool现代模块机制的命名空间,简单来说就是通过给全局变量添加属性来表示的功能分组。根据命名空间对不同的功能进行分组可以使您的单个全局变量井然有序,同时让团队成员知道应该在哪个部分定义新功能,或者去哪里寻找现有功能。例如:定义一个全局变量Y,Y.DOM下的所有方法都与操作DOM相关,Y.Event下的所有方法都与事件相关。一个常见的用法是为每个单独的JS文件创建一个新的全局变量来声明自己的命名空间;每个文件都需要挂载一个命名空间;这时候需要保证命名空间已经存在,可以在单个全局变量中定义一个方法来处理这个任务:这个方法在创建新的命名空间时不会对已有的命名空间造成破坏,并且没有使用命名空间时需要判断是否存在。varMyGolbal={namespace:function(ns){varparts=ns.split('.'),obj=this,i,len=parts.length;for(i=0;i