读代码简洁之道有感

前言

今天是在公司实习的第二天,在安装好开发软件与配置好开发环境之后,就在我以为终于可以大施拳脚时,leader却给我发来一份前端指导手册,里面是一些新人需要阅读的文档。

就在我大失所望,以为又要辛(mo)苦(yu)一天时发现事情没那么简单。

之前在小公司实习以及个人进行一些项目开发时,很少会去关注到代码的质量,于是写出了很多可能自己看的懂但是却“拿不出手”的代码。而在进入这家稍微规模大一点的公司之后,我发现代码原来不仅是给自己看的,在开发的同时也要考虑到其他开发者的感受。

而这本代码简洁之道以很小的篇幅向我打开了一个新世界的大门。

代码简洁之道的核心内容可以理解为两句话:代码自我注释(注释要做到精简准确),对开发者友好(易于理解,修改和扩展)。

同时在开发过程中要站在其他开发者的角度思考三个问题

“WTF is that?”(这TM是啥?)

“WTF did you do here?”(你TM在做啥?)

“WTF is this for?”(你TM为什么这么做?)
复制代码

一下是代码简洁之道的主要内容外加一些我自己的理解

强类型检查

如果可以,请求永远先使用===而不是==
举个例子

// 如果没有妥善处理的话,可能会出现和预想不一样的结果
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);
}
复制代码

==与===的区别这里简单说一下。

===先比较类型,在类型相等情况下比较值,类型和值都相等才返回true。

==先比较类型,类型不相等则先进行类型转换在比较

这里说的其实并不是很完整,==与===的具体区别以及为什么建议使用===。

请参考Javascript 中 == 和 === 的区别

变量命名

这部分是我之前一直忽略的,相信很多新人小伙伴也和我一样,变量命名不规范不简洁不能做到见名知意。

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

不好的命名方式:

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;
复制代码

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

坏的命名方式:

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;
复制代码

这些例子都是出自与原文章上的,而且大多通过正反对比来举例说明。

这里我给大家推荐一个变量命名自动生成网站以方便大家的开发,开发可以在此网站输入中文以得到响应的规范的英文变量。

CODELF

函数

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

坏的命名方式:

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标签

不要使用 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
    }
}
复制代码

判断条件

避免使用否定的条件

坏的写法:

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...
}
复制代码

ES 类

尽可能使用类

建议使用类而不是用老式的直接定义函数的写法。

坏的写法:

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();
复制代码

其它

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

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享