一般咱们在作项目的时候通常会出现这样的一种状况。html
<script> // a.js var varity=1; function changeHTML(){ //define function changeHTML } function decodeHTML(){ // define function decodeHTML } //……………… </script>
main.html的引入前端
<html> <body></body> <script src="a.js"></script> </html>
这个按照咱们正常的写法上面来讲是没有什么问题的,至少在使用上面没有问题,可是却存在一些隐患node
1. 假设后来有A同事须要添加一个方法叫作decodeString来处理string文本,B同事若是也要添加一个相似的方法,那么就不可以使用decodeString来命名,除此以外这样的函数定义也会直接把函数暴露到全局中。浏览器
2. 变量也会被散乱分布到全局变量中,后续变量命名就会有命名冲突的隐患缓存
3. 若是是函数与函数之间的依赖关系比较难维护等问题服务器
对于这样的一种状况最开始谷歌的YUI提出的解决方案是与PHP,JAVA的解决方案类似就是添加一个命名空间。闭包
上面的代码咱们能够这样的去编写。模块化
<script> // a.js // 变量 var variable={};//全局中只有惟一的一个variable,用来保存全部的变量 variable.varity=1; // 方法 var methods={};//全局中只有惟一的一个methods,用来保存全部的方法
var methods.common={}; methods.common.changeHTML=function(){ //define function changeHTML
alert(1);
} methods.common.decodeHTML = function () { //define function decodeHTML } </script>
咱们发现这样的基本上面的这种方法是能够解决一些没必要要的冲突的(除非你是想给本身挖坑),假如咱们要添加一个关于用户登陆的方法,咱们能够这样写。函数
methods.users = {}; methods.users.login=function(str){ console.log(str); } methods.users.login("this is a test");
这样去管理方法和变量虽然相比于第一种方法来讲能够有效的解决冲突,可是也是存在以下的一些问题:测试
1. 若是咱们要调用这个简单的login方法,咱们会发现须要书写一大串的前缀(methods.users.login)。代码编写风格不简洁
2. 变量虽然是能够有效的管理,可是确实没有解决读写的控制,特别是若是团队的人较多的话,容易发生误操做,因此应该进行读写分离。
其实上面对变量的管理已经比较有效了,但只是缺乏读写的控制,容易发生误操做,因此参照ES6的作法,从新编写了一个getter方法和setting方法来获取参数。
var val=function(){ var that=this; var variable={}; variable.varity=1; var returnVal={}; this.isString=function(str){ try { if (typeof str !== "string") { throw "TypeErr"; }else{ return true; } } catch (e) { if (e == "TypeErr") { return false; } } } returnVal.getter=function(str){ var isStr=that.isString(str); if(isStr){ return variable[str]; }else{ console.error("input type must string!!!!!"); } } returnVal.setter=function(key,value){ var isStr=that.isString(key); if(isStr){ if(variable[key]==undefined){ eval(variable[key]); } variable[key]=value; }else{ console.error("input type must string!!!!!"); } } return returnVal; }
运行代码测试:
var val= val();//初始化方法 console.log(val.getter("varity"));// 1 val.setter("va222rity",3);//不存在从新添加并赋值 console.log(val.getter("va222rity")); // 3
如今这样写变量就不容易发生误操做了(读写已经分离),也不会把变量泄漏到全局中去。
上面的函数就是对闭包的一个实际的应用。具体不懂的能够自行百度闭包的知识(具体还能够实现的更加的简洁,在这里不累赘)。
变量相关的优化方案咱们已经说了,咱们接下来讲一说关于函数模块化的应用。
模块化最先是由node.js提出来的一种规范,具体的实现是CommonJS
可是因为服务器端与浏览器端的不一样,不一样之处主要表如今服务器端加载文件是经过缓存读取本地文件的形式来实现的,因此加载的时间能够忽略不计,可是在浏览器端(前端)却不是这样的,每一个文件都是经过HTTP请求从服务器中下载而来,因此中间会产生必定的加载时间,因此浏览器端和服务器端你是不一样的。
采用的方式是按需加载,也就是说何时须要就何时加载这个文件进来
共同点:都是实行对代码的预先加载
异同点:RequireJS提出的观点是预先加载并执行[早期],SeaJS提出的观点是预先加载,按需执行。
相比之下,做者更倾向于RequireJS的实现方式,具体缘由以下
1.RequireJS社区和文档的支持比较完善
2,SeaJS项目中止维护
3.RequireJS在后续的版本中含括了SeaJS的功能
在实际的应用之中,通常模块化是用来解决如下的几种状况的:
1. 解决文件与文件之间相互的依赖关系所产生的问题,方便后期代码的升级维护。
2. 解决过渡加载不须要的函数代码
3. 函数直接不会泄漏到全局
具体的用法不过多的解释不懂点这里:http://www.zhangxinxu.com/sp/seajs/docs/zh-cn/module-definition.html#define
写这篇文章的时候已是2018年了,这些东西虽然能够用,可是未免有些过期。
该文章主要是讲关于闭包和模块化在项目中要怎样的合理使用,目前模块化最好的解决方案我认为是ES6的module。
可是考虑到团队中可能水平良莠不齐,致使ES6推进的难度。因此建议首选ES6,次选RequireJS。
关于ES6的讲解介绍会在以后的文章说起,若是以为文章对你有帮助请点个赞。