JavaScript代码质量优化实践

248 阅读5分钟

一,let和const的合理使用

1,用let取代var,建议不再使用var;

2,let和const之间,建议优先使用const,尤其是在全局环境,不应该设置变量,只应设置常量;

3,const优于let的几个原因:

  • const可以提醒阅读程序的人,这个变量不应该改变;
  • const比较符合编程思想,运算不改变值,只是新建值,而且有利于将来的分布式运算;
  • JavaScript编译器会对const进行优化,所以多使用const有利于提高程序的运行效率;

4,let用于声明变量,const用于声明常量。

二,字符串的使用

静态字符串一律使用单引号或反引号,不使用双引号。动态字符串使用反引号。

const name = "Lily";    // bab

const name = 'Lily';    // good
const age = `${age}岁`; // good

三,解构赋值

1,使用数组成员对变量赋值时,优先使用解构赋值。

const arr = [11,22,33];
const [first, second] = arr;

2,函数的参数如果是对象的成员,优先使用解构赋值。

// bad
function getFullName(user){
    const firstName = user.firstName;
    const lastName = user.lastName;
};
// good
function getFullName(obj){
    const {firstName, lastName} = obj;
}
// best
function getFullName({firstName, lastName}){}

3,如果函数返回多个值,优先使用对象的解构赋值,而不是数组的解构赋值。这样便于以后添加返回值,以及更改返回值的顺序。

function processInput(input){
    return { left, right, top, bottom };
}
const { left, right } = processInput(input);

4,请求参数中去掉多余的字段

params = {
   x1: 1,
   x2: 2,
   x3: 3,
   x4:4
};
// bad
delete params.x1;
const otherParams = params;
// best
const {x1, ...otherParams} = params;

四,对象

1,对象尽量静态化,一旦定义,就不得随意添加新的属性。如果添加属性不可避免,要使用Object.assign方法。

const obj = {
    id:1,
    name: 'xyj'
};

// bad
obj.x = 3;
// good(ES5)
const newObj = Object.assign(obj, {x: 3});
// best(ES6)
const newObj = {
    ...obj,
    x:3
}

2,如果对象的属性名是动态的,可以在创造对象的时候,使用属性表达式定义。

const getKey = function(k){
    return k;
}
const obj = {
    name: 'xyj',
    age: 5,
    [getKey('show')]: true
}

3,对象的属性和方法,尽量采用简洁表达法,这样易于描述和书写。

var ref = 'some value';
const atom = {
    ref,
    value: 1,
    addValue(value){
        return atom.value + value;
    }
};

五,数组

1,使用扩展运算符(...)拷贝数组。

const arr = [1,3,4,5,6];
const copyArr = [...arr];

2,使用Array.from方法,将类数组的对象转为数组。

const foo = document.querySelectorAll('.foo');
const nodes = Array.from(foo);

3,巧用Array.filter()

checkbox的选中与不选中

const initList = [];
// bad
const index = initList.fondIndex(k => k.id = this.id)
const list = initList.splice(index, 1);
// best
const list = initList.filter(k => k.id !== this.id);

六,函数

1,立即执行函数可以写成箭头函数的形式。

(() => {
    console.log('Welcome to the Internet');
})();

2,那些使用了匿名函数当做参数的场合,尽量用箭头函数代替。因为这样更简洁,而且绑定了this。

// bad 
[1,2,3].map(function(x){
    return x*x;
});

// good
[1,3,4].map((x) => {
    return x*x;
});

// best
[1,3,4].map(x => x*x);

3,箭头函数取代Function.prototype.bind。不应再用self/_this/that绑定this。

// bad
const self = this;
const boundMethod = function(...params){
    return method.apply(self, params);
};
// best
const boundMethod = (...params) => method.apply(this, params);

简单的、单行的、不会复用的函数,建议采用箭头函数。

4,不要在函数体内使用arguments变量,使用rest运算符(...)代替。

因为rest运算符显式表明你想要获取参数,而且arguments是一个类似数组的对象,而rest运算符可以提供一个真正的数组。

// bad
function conAll() {
    const args = Array.prototype.slice.call(arguments);
    return args.join('');
};
// good
function conAll(...args){
    return args.join('');
}

5,使用默认值语法设置函数参数的默认值。

function handleThings(opts){
    opts = opts || {};
}

// good
function handleThings(opts = {}){
    // ...
}

七,try...catch的使用

1,正常情况下,await后面是一个Promise对象。为了防止Promise对象抛出异常从而终止后面的操作,将await放在try...catch语句中

// 不用try...catch,Promise执行异常后会终止后面的执行
async function fun(){
    await new Promise((resolve, reject) => {
        throw new Error('出错了');
    });
    return await('hello world!');
}
fun(); // Uncaught (in promise) Error: 出错了

// 使用try...catch,Promise执行异常后也不会终止后面的执行
async function fun(){
    try{
        await new Promise((resolve, reject) => {
            throw new Error('出错了');
        })
    } catch (err) {
        console.log(err);
    };
    return await('执行了hello world');
};
fun();

2,使用JSON.parse()的时候

let obj = {};
try{
    obj = JSON.parse('{"x":5,"y":6}');
} catch (err) {
    console.log(err);
}

3,规避浏览器原罪的场合和非法语句的执行。

八,if...else/三目运算/switch的合理使用

1,if...else的合理使用

if...else的合理使用,不仅可以让代码看起来简洁,而且也避免了很多冗余的代码。能用三目运算和switch等替代的,尽量不要使用if...else;

let name = 'Lucy';
// bad
if (name) {
    name = 'Lucy';
} else {
    name = '';
}
// good
name = 'Lucy' || '';

2,三目运算的使用

let yearText = '';
const year = (new Date()).getFullYear();
// bad
if (year%4 === 0 && year%100!==0 || year % 400 === 0) {
    yearText = '闰年';
} else {
    yearText = '平年';
}
// good
yearText = (year%4 === 0 && year%100 !== 0) ? '闰年' : (year%400 === 0 ? '闰年' : '平年');

3,switch的使用

const day = (new Date()).getDay();
let dayText = '';
// bad
if (day === 0) {
   dayText = '日';
} else (day === 1) {
    dayText = '一';
} else (day === 2) {
    dayText = '二';
}...

// good 
switch(day){
   case 0: 
        dayText = '日';
        break;
    case 1:
        dayText = '一';
        break;
    ...
    default:
        break;
}

九,何时使用==和===

const obj = {
    a: undefined
};
if (obj.a == null) {
    console.log('执行');
}

undefined == null;  // true

如果obj.a === null || obj.a === undefined的时候,使用==;其它都使用===

十,Code Review

之前,在一篇掘金文章中,看到这么一句话:“没有code review的团队就没有未来“,诚然,code review,就像工厂的质检员;没有code review,就没有质检员,团队成员之间的成长也无从谈起,那么团队的负责人也就不关心团队成员的成长,久而久之,不合格的代码也会进入代码库,故code review是检查代码质量必不可少的一个环节。