Clean Code之JavaScript代码示例

时间: 2019-06-11阅读: 36标签: 代码
译者按: 简洁的代码可以避免写出过多的BUG。

引文

作为一个开发者,如果你关心代码质量,除了需要认真测试代码能否正确执行以外,还要注重代码的整洁(clean code)。一个专业的开发者会从将来自己或则他人方便维护的角度考虑如何写代码,而不仅仅是机器能够读懂。你写的任何代码有很大几率会被再次重构,希望未来重构代码的那个人不会觉得这是一场灾难。

代码的简洁之道可以被理解为:代码自我解释(且注释少),开发者友好(易于理解,修改和扩展)。

想想之前阅读别人的代码的时候,说过多少次下面的话?

"WTF is that?"
"WTF did you do here?"
"WTF is this for?"

下面这张图很形象地描述了这个情况:


《Clean Code》的作者Robert C. Martin (Uncle Bob) 说过这样的话.

虽然烂代码可以运行,但是它不够整洁,它会把整个开发团队给整跪了

本文主要讲 JavaScript 代码的整洁之道。


1. 强类型检查

建议使用 === 而不是 == 来判断是否相等

// 如果没有妥善处理的话,可能会出现和预想不一样的结果
0 == false; // true
0 === false; // false
2 == "2"; // true
2 === "2"; // false

const value = "500";
if (value === 500) {
    // 不会执行
    console.log(value);
}

if (value === "500") {
    // 会执行
    console.log(value);
}


2. 变量命名

变量命名尽量直观易懂,方便查找;而且其他开发者也容易理解。

不好的命名方式:

let daysSLV = 10;
let y = new Date().getFullYear();

let ok;
if (user.age > 30) {
    ok = true;
}

好的命名方式:

const MAX_AGE = 30;
let daysSinceLastVisit = 10;
let currentYear = new Date().getFullYear();

...

const isUserOlderThanAllowed = user.age > MAX_AGE;

不要使用多余的无意义的单词来组合命名

坏的命名方式:

let nameValue;
let theProduct;

好的命名方式:

let name;
let product;

不要使用无意义的字符/单词来命名,增加额外的记忆负担

坏的命名方式:

const users = ["John", "Marco", "Peter"];
users.forEach(u => {
    doSomething();
    doSomethingElse();
    // ...
    // ...
    // ...
    // ...
    // 这里u到底指代什么?
    register(u);
});

好的命名方式:

const users = ["John", "Marco", "Peter"];
users.forEach(user => {
    doSomething();
    doSomethingElse();
    // ...
    // ...
    // ...
    // ...
    register(user);
});

在某些环境下,不用添加冗余的单词来组合命名。比如一个对象叫user,那么其中的一个名字的属性直接用name,不需要再使用username了。

坏的命名方式:

const user = {
  userName: "John",
  userSurname: "Doe",
  userAge: "28"
};

...

user.userName;

好的命名方式:

const user = {
  name: "John",
  surname: "Doe",
  age: "28"
};

...

user.name;


3. 函数

请使用完整的声明式的名字来给函数命名。比如一个函数实现了某个行为,那么函数名可以是一个动词或则一个动词加上其行为的被作用者。名字就应该表达出函数要表达的行为。

坏的命名方式:

function notif(user) {
    // implementation
}

好的命名方式:

function notifyUser(emailAddress) {
    // implementation
}

避免使用过多参数。最好一个函数只有 2 个甚至更少的参数。参数越少,越容易做测试。

坏的使用方式:

function getUsers(fields, fromDate, toDate) {
    // implementation
}

好的使用方式:

function getUsers({ fields, fromDate, toDate }) {
    // implementation
}

getUsers({
    fields: ["name", "surname", "email"],
    fromDate: "2019-01-01",
    toDate: "2019-01-18"
});

为函数参数设置默认值,而不是在代码中通过条件判断来赋值。

坏的写法:

function createShape(type) {
    const shapeType = type || "cube";
    // ...
}

好的写法:

function createShape(type = "cube") {
    // ...
}

一个函数应该只做一件事情。避免将多个事情塞到一个函数中。

坏的写法:

function notifyUsers(users) {
    users.forEach(user => {
        const userRecord = database.lookup(user);
        if (userRecord.isVerified()) {
            notify(user);
        }
    });
}

好的写法:

function notifyVerifiedUsers(users) {
    users.filter(isUserVerified).forEach(notify);
}

function isUserVerified(user) {
    const userRecord = database.lookup(user);
    return userRecord.isVerified();
}

使用Objecg.assign来设置默认对象值。

坏的写法:

const shapeConfig = {
    type: "cube",
    width: 200,
    height: null
};

function createShape(config) {
    config.type = config.type || "cube";
    config.width = config.width || 250;
    config.height = config.width || 250;
}

createShape(shapeConfig);

好的写法:

const shapeConfig = {
  type: "cube",
  width: 200
  // Exclude the 'height' key
};

function createShape(config) {
  config = Object.assign(
    {
      type: "cube",
      width: 250,
      height: 250
    },
    config
  );

  ...
}

createShape(shapeConfig);

不要使用 true/false 的标签(flag),因为它实际上让函数做了超出它本身的事情。

坏的写法:

function createFile(name, isPublic) {
    if (isPublic) {
        fs.create(`./public/${name}`);
    } else {
        fs.create(name);
    }
}

好的写法:

function createFile(name) {
    fs.create(name);
}

function createPublicFile(name) {
    createFile(`./public/${name}`);
}

不要污染全局。如果你需要对现有的对象进行扩展,不要在对象的原型链上定义函数。请使用 ES 的类和继承。

坏的写法:

Array.prototype.myFunc = function myFunc() {
    // implementation
};

好的写法:

class SuperArray extends Array {
    myFunc() {
        // implementation
    }
}


4. 判断条件

避免使用否定的条件。

坏的写法:

function isUserNotBlocked(user) {
    // implementation
}

if (!isUserNotBlocked(user)) {
    // implementation
}

好的写法:

function isUserBlocked(user) {
    // implementation
}

if (isUserBlocked(user)) {
    // implementation
}

使用简短的条件。这个要求看上去简单,但是值得提醒。

坏的写法:

if (isValid === true) {
    // do something...
}

if (isValid === false) {
    // do something...
}

好的写法:

if (isValid) {
    // do something...
}

if (!isValid) {
    // do something...
}

如果你很确定它的值不是undefined或则null,我建议你这么做。尽量避免使用判断条件,推荐说那个多态(polymorphism)或则继承。

坏的写法:

class Car {
    // ...
    getMaximumSpeed() {
        switch (this.type) {
            case "Ford":
                return this.someFactor() + this.anotherFactor();
            case "Mazda":
                return this.someFactor();
            case "McLaren":
                return this.someFactor() - this.anotherFactor();
        }
    }
}

好的写法:

class Car {
    // ...
}

class Ford extends Car {
    // ...
    getMaximumSpeed() {
        return this.someFactor() + this.anotherFactor();
    }
}

class Mazda extends Car {
    // ...
    getMaximumSpeed() {
        return this.someFactor();
    }
}

class McLaren extends Car {
    // ...
    getMaximumSpeed() {
        return this.someFactor() - this.anotherFactor();
    }
}


5. ES 类

类是 JavaScript 新推出的语法糖。建议使用类而不是用老式的直接定义函数的写法。

坏的写法:

const Person = function(name) {
    if (!(this instanceof Person)) {
        throw new Error("Instantiate Person with `new` keyword");
    }

    this.name = name;
};

Person.prototype.sayHello = function sayHello() {
    /**/
};

const Student = function(name, school) {
    if (!(this instanceof Student)) {
        throw new Error("Instantiate Student with `new` keyword");
    }

    Person.call(this, name);
    this.school = school;
};

Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;
Student.prototype.printSchoolName = function printSchoolName() {
    /**/
};

好的写法:

class Person {
    constructor(name) {
        this.name = name;
    }

    sayHello() {
        /* ... */
    }
}

class Student extends Person {
    constructor(name, school) {
        super(name);
        this.school = school;
    }

    printSchoolName() {
        /* ... */
    }
}

使用函数调用链。像 jQuery,Lodash 都使用这个模式。你只需要在每一个函数的末尾返回this,之后的代码会更加的简洁。

坏的写法:

class Person {
    constructor(name) {
        this.name = name;
    }

    setSurname(surname) {
        this.surname = surname;
    }

    setAge(age) {
        this.age = age;
    }

    save() {
        console.log(this.name, this.surname, this.age);
    }
}

const person = new Person("John");
person.setSurname("Doe");
person.setAge(29);
person.save();

好的写法:

class Person {
    constructor(name) {
        this.name = name;
    }

    setSurname(surname) {
        this.surname = surname;
        // Return this for chaining
        return this;
    }

    setAge(age) {
        this.age = age;
        // Return this for chaining
        return this;
    }

    save() {
        console.log(this.name, this.surname, this.age);
        // Return this for chaining
        return this;
    }
}

const person = new Person("John")
    .setSurname("Doe")
    .setAge(29)
    .save();


6. 其它

总的来说,你不能写重复代码,不能留下一堆不再使用的函数,永远不会执行的代码(死代码)。

在很多情况下,你可能搞出重复代码。比如你要实现两个略微不同的功能,他们有很多相通的地方,但是由于项目截止时间快到了,你不得不快速复制黏贴再稍微修改修改来实现。

对于死代码,最好的做法就是你决定不再使用它的那一刻就把它删掉。时间过去太久,你甚至会忘记自己当初为什么定义它。下面这幅图很形象地描述了这个情况:



关于Fundebug

Fundebug专注于JavaScript、微信小程序、微信小游戏、支付宝小程序、React Native、Node.js和Java线上应用实时BUG监控。 自从2016年双十一正式上线,Fundebug累计处理了10亿+错误事件,付费客户有Google、360、金山软件、百姓网等众多品牌企业

本文采用意译,版权归原作者所有


什么样的代码叫好代码?

代码的本质还要在机器上运行,好的代码不单单的纯粹的简单的几个字符的问题,好的代码不仅仅是排版上或者语法上好看,还要能经过产品的测试验证,这是评判代码好坏的最准确的标准

Js代码简洁之道

如果你关注代码本身和代码的编写方式,而不是只关心它是否能工作,那么你写代码是有一定的水准。专业开发人员将为未来的自己和“其他人”编写代码,而不仅仅只编写当前能工作就行的代码。

前端业务代码配置化

如何写好业务代码? 在前端工作中有很多业务性代码,如果书写不规范,那么对后期的维护将是非常致命的。业务场景:后端数据库中经常会一个字段具备几个不同的状态

使用React Hook提高代码复用性

Hook 是 React 16.8 的新增特性。是对 React 函数组件的一种扩展,通过提供一些特殊的函数,让无状态的组件拥有状态组件才拥有的能力。没有Hook之前写组件有两种形式,分别为:函数组件,class组件

JS无形装逼,最为致命

单行简洁的代码很难维护(有时甚至难以理解),但这并不能阻止广大攻城狮们脑洞,在编写简洁的代码后获得一定的满足感。以下我最近的一些收藏javascript精简代码集合。

用什么工具保证一致的代码风格?

首先这个问题展开来讲就是:如何在Node.js模块编写中保持代码一致性风格,目前来说基本上有四种工具可以完成JSLint,JSHint,JSCS,ESLint。

Js代码压缩工具推荐

JavaScript 代码压缩是指去除源代码里的所有不必要的字符,而不改变其功能的过程。这些不必要的字符通常包括空格字符,换行字符,注释以及块分隔符等用来增加可读性的代码,但并不需要它来执行。

怎样使你的 JavaScript 代码简单易读

解决一个问题可以有很多方法,但是有些方法很复杂,甚至有些是荒谬的。在本文中,我想谈谈解决一个问题时的好方案和坏方案。

怎么避免写出烂代码

命名规则:除非在小于 5 行的函数里,否则不要使用单字命名变量,规则:不要使用名词加数字的命名方法,规则:应该且只有方法和函数以动词开头

除了敲代码,你还有什么副业吗?

作为一名程序员,除了敲代码之外的一些副业!什么是副业?副业就是主要事业以外附带经营的事业。我们都是程序员,大多数都是普通人,都在替别人打工,虽然收入在别人眼中挺高,但是在霸都连个首付都付不起。

fly63.com版权所有,内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权,请与小编联系!情况属实本人将予以删除!

广告赞助文章投稿关于web前端网站点搜索站长推荐网站地图站长QQ:522607023

小程序专栏: 土味情话心理测试脑筋急转弯幽默笑话段子句子语录成语大全