Javascript Patterns--读书笔记2

Writing Maintainable code

有人愿意修bug吗?这不是废话吗?(反正我不愿意修),bug总是不可避免的,我们会花大量的时间来修bug,下面的时间总是我们不可避免的:

  • 搞清楚是什么问题
  • 理解code,然后再去尝试解决问题

如果在一个大的公司或者是一个大的项目中,我们花在第一项的时间会很多。

所以我们在写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声明在一起模式:

好处:

  • 提供一个地方来声明函数所需要的所有变量
  • 避免一个变量在没有声明之前就被使用了。
  • 帮助你记得声明变量而且minimize globals

JSLint在检查代码时,会提示,如果你的所有var不是写在一处会是一个错误

for:

如果我们在用for时,对一个数组,或者是一个dom collection做循环时,最好时可以用一个变量来代替 array.length;这样可以减少对一个数组或者是对象的访问次数来达到提高效率的目的。详情可以看Nicholas Zakas:High Performance Javascript 另外我们在做循环时用到的循环变量要放在前边声明:

View Code
function looper(){
  var i=0,
        max,
        myarray=[];
    
  for (i = 0, max = myarray.length; i <  max; i++){
    }    
}

for-in:

它可以用来对一个nonarray objects做一个遍历。当然我们也可以用for in对array来遍历,但是是不被推荐的,基于下边两点:

  • 如果我们对这个array object已经被扩展了,例如加上一些自定义属性,函数。
  • 另外,它的顺序也不是可以保证的

不要扩展built-in Prototypes

如果我们扩展一些内置的prototypes的时候,如Array(), Function(), Object()当别的程序员来用它的时候就会产生莫名的问题。

 当然这里有些情况下是我们可以扩展的:

1. 如果一些函数是未来的ECMAScript所期盼的实现,我们可以来实现这些内置的功能。如ECMAScript5中的一些内置函数。

2.添加一些在别的browser中的JS Engine已经实现了的函数。

3.你已经清楚的在文档中写出来了,并且和team的其他成员已经沟通过了。

避免隐式的类型转换:

我们要避免用==来代替===,因为JS在比较的时候会做隐式的转换

View Code
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");

命名规范:

  • 用大写字母对Constructor()来命名
  • 单词之间要分开getFirst()
  • 常量要全部大写
  • 私有的要这样写:_private() 
posted @ 2012-09-07 18:08  moonreplace  阅读(193)  评论(0编辑  收藏  举报