Writing Maintainable code
有人愿意修bug吗?这不是废话吗?(反正我不愿意修),bug总是不可避免的,我们会花大量的时间来修bug,下面的时间总是我们不可避免的:
如果在一个大的公司或者是一个大的项目中,我们花在第一项的时间会很多。
所以我们在写code的时候需要遵守一些规则:
Minimizing Globals
JS是用functions来管理scope的。如果一个变量声明在一个function内,那么它就是一个本地变量,在外部是不可用的。那么global的变量是在任何function的外部所声明的,或者是干脆没声明的。
如果我们用this关键字在任何的函数之外,那么this引用的就是global(window, self), 我们所创建的每一个全局变量都会成为global object(window)的一个属性。
myglobal="hello";//这是不好的,不用var来声明 console.log(myglobal);//hello console.log(window.myglobal);//hello console.log(window["myglboal"]);//hello console.log(this.myglobal);//hello
Global所带来的问题:
它们会被所有的code所访问,所以有可能会有命名冲突,从而导致,你把别人的变量给override掉了,所以会出现一些问题。这种情况是比较常见的,如果我们引入了一个第三方的库jQuery,广告公司的script.
那我们如何来避免呢,请记住在任何地方声明变量时,都要用var:
function sum(x,y){ //antipattern: implied global result = x+y; return result; } function sum(x,y){ var result = x+y; return result; }
还有下面的代码也是必须要禁止的:
function foo(){ var a=b=0;//b会是一个全局变量 }
它实际上变成了
var a=(b=0);
如果我们声明一个全局变量的时候,没有用var,那么这个全局变量是可以删掉的,否则,它就是不可删除的,看代码:
var global_var=1; global_novar=2;//antipattern (function(){ global_fromfunc=3;//antipattern })(); //attempt to delete delete global_var;//false delete global_novera;//true; delete global_fromfunc;//true; //test the deletion typeof global_var;//'number' typeof global_novar; //undefined typeof global_fromfunc;//"undefined
在ES5 strict mode下,如果我们试图给一个没有声明过的变量赋值,会得到一个抛出的异常。
访问全局变量:
如果是在browser中,我们可以得用window, self来访问全局变量,但是如果我们的宿主环境不是browser,那如何办,来看下面的代码:
var global=(function(){ return this; }());
所有的变量用var声明在一起模式:
好处:
JSLint在检查代码时,会提示,如果你的所有var不是写在一处会是一个错误
for:
如果我们在用for时,对一个数组,或者是一个dom collection做循环时,最好时可以用一个变量来代替 array.length;这样可以减少对一个数组或者是对象的访问次数来达到提高效率的目的。详情可以看Nicholas Zakas:High Performance Javascript 另外我们在做循环时用到的循环变量要放在前边声明:
function looper(){ var i=0, max, myarray=[]; for (i = 0, max = myarray.length; i < max; i++){ } }
for-in:
它可以用来对一个nonarray objects做一个遍历。当然我们也可以用for in对array来遍历,但是是不被推荐的,基于下边两点:
不要扩展built-in Prototypes
如果我们扩展一些内置的prototypes的时候,如Array(), Function(), Object()当别的程序员来用它的时候就会产生莫名的问题。
当然这里有些情况下是我们可以扩展的:
1. 如果一些函数是未来的ECMAScript所期盼的实现,我们可以来实现这些内置的功能。如ECMAScript5中的一些内置函数。
2.添加一些在别的browser中的JS Engine已经实现了的函数。
3.你已经清楚的在文档中写出来了,并且和team的其他成员已经沟通过了。
避免隐式的类型转换:
我们要避免用==来代替===,因为JS在比较的时候会做隐式的转换
var zero=0; if(zero===false){ //不会被执行,因为0不等于false } //antiPattern if(zero==false){ //this block is executed... }
不要用eval(),我们在传给setTimeout()或者setInterval()的时候不要传string
Number转换的时候用parseInt()
在ES3中,我们以0开头的时候,它会当成8进制的数字,所以我们可以进行显式的转换:
parseInt(month, 10);
另外的方式也很好:+"08", Number("08");
命名规范: