如何编写可维护的优雅代码

1,377 阅读6分钟

程序是写给人读的,只是偶尔让计算机执行一下。就执行而言,计算机只关心对错,但是就团队协作而言,风格一致且优雅的代码,会让人看上去赏心悦目(痛哭流涕)。因此,确定编码风格,就尤为重要

本文就javascript而言,对于使用vue等框架,使用Eslint或者团队已经强制推行自己的风格,仅供参考

缩进

4个空格(制表符)

一般编辑器按下tab时,默认是4个空格。因此,小编推荐4个空格,至少看上去是最舒服的

推荐指数: 🌟🌟

语句结尾

以;(分号)结尾

有赖于分析器的分号自动插入机制,js代码省略分号也是可以正常工作的。就JSLint和JSHint而言,省略空格,都会有警号。还有更麻烦的是,如果js是下面这5个字符之一,js就不会对上一行自动添加分号 ( [ / + -

x = y
(function () {

})()

便会等价于

x = y(function () {

})()

推荐指数: 🌟🌟🌟🌟

空行

在编码规范中,空行是最容易忽视的一方面。而且,就编程人员而言,仁者见仁,智者见智。下面,小编就简单阐述一下自己的见解。

什么时候要有空行?

  1. 方法和方法之间
function getName () {
    // 代码块
}   

function getAge () {
    // 代码块
}

推荐指数: 🌟🌟

  1. 变量和函数之间要空行
var name = null

function getName () {
    
}

推荐指数: 🌟🌟🌟🌟 3. 在多行与上一行注释前

/*
    取得属性值name
*/
var name = null

/*
    取得属性值age
*/
var age = null

推荐指数: 🌟🌟🌟

换行

当一行长度受到单行最大字符限制,或者一行过长影响代码阅读时,需要我们手动拆成多行。此时,我们需要在运算符换行,运算符写在上一行的末尾。

  1. 赋值 给变量赋值时,第二行应该与第一行赋值运算符后的变量对齐
var result = name + age + gender + 
             msg + like; 

推荐指数: 🌟🌟

  1. 运算 运算符后进行换行,下一行会增加1~2个缩进。小编通常使用1个缩进
if (year == '2019' && month == '8' &&
  day == '23') {
      // 代码块
 }

推荐指数: 🌟🌟

变量和函数

只要写代码,就在声明变量和函数,或者走在声明变量和函数的路上。因此,变量和和函数声明的可读性就至关重要。

变量

声明变量的长度要尽可能短,并抓住要点,且尽可能的体现数据类型。对于数组,一般采用 +s 的复数形式

/*
    好的做法
*/
var count = 1;
var name = 'jack'
var status = false 
var names = ['jack', 'john', 'dave']

/*
    不好的做法
    变量声明向函数,容易产生误解
*/
var getCount = 10
var getName = 'jack'
var isUse = false

推荐指数: 🌟🌟🌟

函数

对于函数来说,第一个单词最好是动词,如get, set, has, is, toggle, can, delete, update, insert, add等,推荐使用驼峰明明法。函数的长度一定要见明知意,哪怕长度稍微长一点,都是值得的

/*
    好的做法
*/
function getName () {
    return name
}

function checkPermissionsBySession () {

}

推荐指数: 🌟🌟🌟🌟

大括号

起首的大括号要跟在关键字的后面。因为Javascript会自动添加句末的分号,导致一些难以察觉的错误。为了避免这一类错误,需要写成下面这样

/*
    好的做法
*/
return {
    name: 'jack'
}  

/*
    不好的走法
    解析器会解析 return ; 
    后面的代码就不会执行
*/
return 
{
    name: 'jack'
}  

推荐指数: 🌟🌟🌟🌟

圆括号

一般来说: 所有语法元素与左括号之间,都有一个空格。下面这两种情况除外

  1. 调用函数的时候,语法元素和做括号之间,没有空格
  2. 函数名与参数序列之间,没有空格
/*
    好的写法
*/
if (a === b) {}    

for (let i=0; i<10; i++) {}

return (a + b)

function getName(arr) {

}
getName()

推荐指数: 🌟🌟🌟

null和undefined

null

使用null的最好方式方式是看作一个占位符。而不是用null来检测是否传参,或者检测是否变量初始化

/*
    好的做法
*/
var name = null

function getName () {
    if (!condition) {
        return null
    }
}

/*
    不好的做法
*/
var name;
if (name != null) {

}

function getName(arg1, arg2) {
    if (arg3 != null) {

    }
}

推荐指数: 🌟🌟

undefined

没有被初始化的变量都有一个初始值,即undefined

var age;
console.log(typeof age) // undefined

推荐指数: 🌟🌟

'=='和'===', '!='和'!=='

js具有强制类型转换的机制,强制类型转换会驱使某些变量自动转换成其他不同类型。可能会造成意想不到的结果。虽然使用相等,在开发过程中可能会加快开发速度,但是一旦出现问题,排查起来花费的时间会多得多。因此,小编强烈建议使用全等和不全等

/*
  不好的做法
*/
console.log(1 == true) // true
console.log(0 == '')   // true

推荐指数: 🌟🌟🌟

全局变量

确保你的函数不会对全局变量有依赖,这将增强您对代码的可测试性。尤其是团队开发,尽可能的避免全局变量

  1. 使用命名空间即只定义一个变量空间(如JQuery -> $)。但是当你引用多个js文件时,恰巧这些文件都同时自定义了相同的变量符号。你就悲剧了。
  2. 使用匿名函数
(function(){
  
})();

可能会造成内存消耗多大,甚至内存泄漏等情况

因此,尽可能的不要使用全局变量,如果不得不使用,请使用全部的大写字母进行命名。如:

MAX_SIZE // 推荐

推荐指数: 🌟🌟🌟🌟

松耦合

将js和css进行抽离

松耦合: 当你能够修改一个组件而不需要更改其他的组件。松耦合对于代码维护性至关重要,因为你绝对不希望开发人员在修改代码时,破坏或者改动其他的代码

/*
  好的做法
*/
var el = document.getElementById('div1');
el.classList.add('blue')
document.body.appendChild(el)
    
/*
  不好的做法。没有将css和js进行解藕
*/
var el = document.getElementById('div2');
el.style.width = '200px';
el.style.height = '200px'
el.style.background = 'blue';
document.body.appendChild(el)

推荐指数: 🌟🌟🌟

将html和js进行抽离

/*
  不好的做法。没有实现html和js解藕
*/
var ul = document.createElement('ul');
ul.innerHTML = `
    <li>li</li>
    <li>li</li>
    <li>li</li>
`
document.body.appendChild(ul)

推荐指数: 🌟🌟🌟

配置数据

对于应用中写死的值,可能会频繁的更改。因此,将配置数据从代码中抽离,保存在config对象中,这样对配置数据的修改可以完全和使用这些数据的代码隔离开来

URL = 'http://xxxxx/index.html?xxx=123

推荐指数: 🌟🌟🌟🌟

组件化和模块化

标准的模块应该是“分工明细,职责单一,不牵扯需求逻辑”。就像是钉子,哪里需要往哪里按。使用模块化和组件化避免了造轮子的重复性工作,且降低了耦合,避免了逻辑错误,使你的代码产生质的飞跃

参考资料

  1. 编写可维护的javascript
  2. 阮一峰的网络日志