不知道身为前端er的你有没有过这种体验,几个月前写的代码自己某天回头再看,如果没有详细的注释,发现已经看不懂了,不知道到底是干嘛的了。
如果没有这种体验,那一定有过另一种体验:同事之前写的代码有些没有注释,完全看不懂。
所以说编写可维护的代码为什么要单独开一篇文章说明,就是因为它太重要了,甚至比如果编写js还重要。
今儿就把自己学习到的记录下来,时不时的查阅,看看自己到底有没有做到,也算是一种养成良好习惯的磨练吧。

避免使用全局变量

这点就没什么好说的了。如果你是一个合格的前端er,你就会知道命名冲突究竟是多少蛋疼的事了。

如何访问全局对象

我猜看到这里第一反应应该就是window吧,但是如果我的运行环境不是浏览器呢,这下又怎么办?
最好的办法应该是通过一段自执行的函数返回:

1
2
3
var global = (function () {
return this;
}());

当然,很明显,严格模式下这段代码并不能返回你想要的结果(严格模式下函数的this指向undefined)

单var形式

这个形式有几个优点:

  • 提供了一个单一的地方去寻找功能所需要的所有局部变量
  • 防止变量在定义之前使用的逻辑错误
  • 少代码(类型啊传值啊单线完成)

当然现在ES6出了let和const,有了块级作用域,为了防止变量提升,用let或const会比较好。
(不过使用时需要注意它们的暂时性死区)

1
2
3
4
5
6
7
8
9
function func() {
let a = 1,
b = 2,
sum = a + b,
myobject = {},
i,
j;
// function body...
}

for循环

for循环大家都懂,但是按照书中的说法,如果简单使用var i=0;i>something.length;i++,每次循环都会去找一个something,如果只是简单数组还好,如果循环的是DOM,那就非常糟糕了,要知道不论什么时候,使用DOM都是非常昂贵的。
再者是i++写法,JSLint推荐使用i+=1,解释是“避免过分棘手(excessive trickiness)”
所以完整下来应该就是:

1
2
3
for(let i=0,max=something.length;i<max;i+=1){
//something[i]...
}

for-in枚举

该方法用于对象的枚举,虽然数组也可以使用此方法(数组也是对象),但并不推荐,原因是:

如果数组对象已被自定义的功能增强,就可能发生逻辑错误。另外,在for-in中,属性列表的顺序(序列)是不能保证的。所以最好数组使用正常的for循环,对象使用for-in循环。

对象的循环本没有什么可说的,但是有个非常强大的东西——原型链,对象会继承原型链下的属性和方法,但常常我们不需要这些属性和方法,于是hasOwnProperty()方法就非常有用了,它:

函数用于指示一个对象自身(不包括原型链)是否具有指定名称的属性。如果有,返回true,否则返回false。

1
2
3
4
5
6
7
8
9
10
11
12
//第一种使用
for (var i in man) {
if (man.hasOwnProperty(i)) { // 过滤
console.log(i, ":", man[i]);
}
}
//第二种使用
for (var i in man) {
if (Object.prototype.hasOwnProperty.call(man, i)) { // 过滤
console.log(i, ":", man[i]);
}
}

如果结合单var形式,写成这样是最优的:

1
2
3
4
5
6
let i, hasOwn = Object.prototype.hasOwnProperty;
for (i in man) {
if (hasOwn.call(man, i)) { // 过滤
console.log(i, ":", man[i]);
}
}

使用switch

可以通过类似下面形式的switch语句增强可读性和健壮性:

1
2
3
4
5
6
7
8
9
10
11
12
var inspect_me = 0,
result = '';
switch (inspect_me) {
case 0:
result = "zero";
break;
case 1:
result = "one";
break;
default:
result = "unknown";
}

switch不仅能让代码看起来简洁,而且非常高高效。

命名

具体的请参阅这篇文章
这里只大概列举几点:

  • 驼峰式命名
  • 变量名以名词开头
  • 方法名以动词开头
  • 常量全部大写
  • 构造函数以大写字母开头

其它

以前有写过一个关于写js的一些规范或者说是自己看完一些文章后的沉思吧,也一并放出来分享了。

一段好的代码应该是怎样的?

试想,当你在学一个业务代码的时候,你是否想过如果参数不是我想要的会怎样、如果出现了异常错误会怎样、如果突然要改需求了会怎样、如果这个参数不存在会怎样,我想都是没有的,你只是关注了结果,却始终没有考虑过边界状态,没有考虑过异常、兼容性以及校验,这很糟糕,非常糟糕。
所以一段好的代码应该是怎样的呢?
1.可用

必须确保自己写的代码是可以正常运行并得到想要的结果的,否则那就是无效代码.

2.健壮

①当存在参数或需要用户输入时,是否判断参数、用户输入存在?
②当参数或用户输入不符合要求时,是否做处理?
③当你使用的方法可能在别的浏览器不兼容时,是否做处理?

3.可靠

是否在所有情况下都能输出一个可靠的值?

4.宽容

①是否有足够的注释,让其他开发人员读懂?
②是否能在需求更改时快速更改而不需要大动干戈?
③当参数或用户输入不符合要求时,是否能将其转成可用参数?

一个例子

要求:编写一个javscript函数 fn,该函数有一个参数 n(数字类型),其返回值是一个数组,该数组内是 n 个随机且不重复的整数,且整数取值范围是 [2, 32]。

代码:

example