JavaScript规范全局命名空间污染与IIFE总是将代码包裹成一个IIFE(Immediately-InvokedFunctionExpression),用以创建独立隔绝的定义域。这一举措可防止全局命名空间被污染。IIFE还可确保你的代码不会轻易被其它全局命名空间里的代码所修改(i.e.第三方库,window引用,被覆盖的未定义的关键字等等)。不推荐1.varx=10,2.y=100;3.4.//Declaringvariablesintheglobalscopeisresultinginglobalscopepollution.Allvariablesdeclaredlikethis5.//willbestoredinthewindowobject.Thisisveryuncleanandneedstobeavoided.6.console.log(window.x+''+window.y);复制代码推荐1.//WedeclareaIIFEandpassparametersintothefunctionthatwewillusefromtheglobalspace2.(function(log,w,undefined){3.'usestrict';4.5.varx=10,6.y=100;7.8.//Willoutput'truetrue'9.log((w.x===undefined)+''+(w.y===undefined));10.11.}(window.console.log,window));复制代码IIFE(立即执行的函数表达式)无论何时,想要创建一个新的封闭的定义域,那就用IIFE。它不仅避免了干扰,也使得内存在执行完后立即释放。所有脚本文件建议都从IIFE开始。立即执行的函数表达式的执行括号应该写在外包括号内。虽然写在内还是写在外都是有效的,但写在内使得整个表达式看起来更像一个整体,因此推荐这么做。不推荐1.(function(){})();复制代码推荐1.(function(){}());复制代码so,用下列写法来格式化你的IIFE代码:1.(function(){2.'usestrict';3.4.//Codegoeshere5.6.}());复制代码如果你想引用全局变量或者是外层IIFE的变量,可以通过下列方式传参:1.(function($,w,d){2.'usestrict';3.4.$(function(){5.w.alert(d.querySelectorAll('div').length);6.});7.}(jQuery,window,document));复制代码严格模式ECMAScript5严格模式可在整个脚本或独个方法内被激活。它对应不同的javascript语境会做更加严格的错误检查。严格模式也确保了javascript代码更加的健壮,运行的也更加快速。严格模式会阻止使用在未来很可能被引入的预留关键字。你应该在你的脚本中启用严格模式,最好是在独立的IIFE中应用它。避免在你的脚本第一行使用它而导致你的所有脚本都启动了严格模式,这有可能会引发一些第三方类库的问题。不推荐1.//Scriptstartshere2.'usestrict';3.4.(function(){5.6.//Yourcodestartshere7.8.}());9.推荐10.11.(function(){12.'usestrict';13.14.//Yourcodestartshere15.16.}());复制代码变量声明总是使用var来声明变量。如不指定var,变量将被隐式地声明为全局变量,这将对变量难以控制。如果没有声明,变量处于什么定义域就变得不清(可以是在Document或Window中,也可以很容易地进入本地定义域)。所以,请总是使用var来声明变量。采用严格模式带来的好处是,当你手误输入错误的变量名时,它可以通过报错信息来帮助你定位错误出处。不推1.x=10;2.y=100;复制代码推荐1.varx=10,2.y=100;复制代码理解JavaScript的定义域和定义域提升在JavaScript中变量和方法定义会自动提升到执行之前。JavaScript只有function级的定义域,而无其他很多编程语言中的块定义域,所以使得你在某一function内的某语句和循环体中定义了一个变量,此变量可作用于整个function内,而不仅仅是在此语句或循环体中,因为它们的声明被JavaScript自动提升了。我们通过例子来看清楚这到底是怎么一回事:原function1.(function(log){2.'usestrict';3.4.vara=10;5.6.for(vari=0;ia;i++){7.varb=i*i;8.log(b);9.}10.11.if(a===10){12.varf=function(){13.log(a);14.};15.f();16.}17.18.functionx(){19.log('Mr.X!');20.}21.x();22.23.}(window.console.log));复制代码被JS提升过后1.(function(log){2.'usestrict';3.//Allvariablesusedintheclosurewillbehoistedtothetopofthefunction4.vara,5.i,6.b,7.f;8.//Allfunctionsintheclosurewillbehoistedtothetop9.functionx(){10.log('Mr.X!');11.}12.13.a=10;14.15.for(i=0;ia;i++){16.b=i*i;17.log(b);18.}19.20.if(a===10){21.//Functionassignmentswillonlyresultinhoistedvariablesbutthefunctionbodywillnotbehoisted22.//Onlybyusingarealfunctiondeclarationthewholefunctionwillbehoistedwithitsbody23.f=function(){24.log(a);25.};26.f();27.}28.29.x();30.31.}(window.console.log));复制代码根据以上提升过程,你是否可理解以下代码?有效代码1.(function(log){2.'usestrict';3.4.vara=10;5.6.i=5;7.8.x();9.10.for(vari;ia;i++){11.log(b);12.varb=i*i;13.}14.15.if(a===10){16.f=function(){17.log(a);18.};19.f();20.21.varf;22.}23.24.functionx(){25.log('Mr.X!');26.}27.28.}(window.console.log));复制代码正如你所看到的这段令人充满困惑与误解的代码导致了出人意料的结果。只有良好的声明习惯,也就是下一章节我们要提到的声明规则,才能尽可能的避免这类错误风险。提升声明为避免上一章节所述的变量和方法定义被自动提升造成误解,把风险降到最低,我们应该手动地显示地去声明变量与方法。也就是说,所有的变量以及方法,应当定义在function内的首行。只用一个var关键字声明,多个变量用逗号隔开。不推荐1.(function(log){2.'usestrict';3.4.vara=10;5.varb=10;6.7.for(vari=0;i10;i++){8.varc=a*b*i;9.}10.11.functionf(){12.13.}14.15.vard=100;16.varx=function(){17.returnd*d;18.};19.log(x());20.21.}(window.console.log));复制代码推荐1.(function(log){2.'usestrict';3.4.vara=10,5.b=10,6.i,7.c,8.d,9.x;10.11.functionf(){12.13.}14.15.for(i=0;i10;i++){16.c=a*b*i;17.}18.19.20.21.d=100;22.x=function(){23.returnd*d;24.};25.log(x());26.27.}(window.console.log));复制代码把赋值尽量写在变量申明中。不推荐1.vara,2.b,3.c;4.5.a=10;6.b=10;7.c=100;复制代码推荐1.vara=10,2.b=10,3.c=100;复制代码总是使用带类型判断的比较判断总是使用===精确的比较操作符,避免在判断的过程中,由JavaScript的强制类型转换所造成的困扰。如果你使用===操作符,那比较的双方必须是同一类型为前提的条件下才会有效。如果你想了解更多关于强制类型转换的信息,你可以读一读DmitrySoshnikov的这篇文章。在只使用==的情况下,JavaScript所带来的强制类型转换使得判断结果跟踪变得复杂,下面的例子可以看出这样的结果有多怪了:1.(function(log){2.'usestrict';3.4.log('0'==0);//true5.log(''==false);//true6.log('1'==true);//true7.log(null==undefined);//true8.9.varx={10.valueOf:function(){11.return'X';12.}13.};14.15.log(x=='X');16.17.}(window.console.log));复制代码明智地使用真假判断当我们在一个if条件语句中使用变量或表达式时,会做真假判断。if(a==true)是不同于if(a)的。后者的判断比较特殊,我们称其为真假判断。这种判断会通过特殊的操作将其转换为true或false,下列表达式统统返回false:false,0,undefined,null,NaN,''(空字符串).这种真假判断在我们只求结果而不关心过程的情况下,非常的有帮助。以下示例展示了真假判断是如何工作的:1.(function(log){2.'usestrict';3.4.functionlogTruthyFalsy(expr){5.if(expr){6.log('truthy');7.}else{8.log('falsy');9.}10.}11.12.logTruthyFalsy(true);//truthy13.logTruthyFalsy(1);//truthy14.logTruthyFalsy({});//truthy15.logTruthyFalsy([]);//truthy16.logTruthyFalsy('0');//truthy17.18.logTruthyFalsy(false);//falsy19.logTruthyFalsy(0);//falsy20.logTruthyFalsy(undefined);//falsy21.logTruthyFalsy(null);//falsy22.logTruthyFalsy(NaN);//falsy23.logTruthyFalsy('');//falsy24.25.}(window.console.log));复制代码变量赋值时的逻辑操作逻辑操作符||和&&也可被用来返回布尔值。如果操作对象为非布尔对象,那每个表达式将会被自左向右地做真假判断。基于此操作,最终总有一个表达式被返回回来。这在变量赋值时,是可以用来简化你的代码的。不推荐1.if(!x){2.if(!y){3.x=1;4.}else{5.x=y;6.}7.}复制代码推荐1