JavaScript 编码之美

前言

这篇文章分享一些代码编写风格,有一些代码可能会需要指定的场景,有些代码则不需要,不管怎么样,我们都可以从中学到如何编写一手高质量、简洁的代码。示例中的代码会尽量使用 ES6 语法编写。

开始

话不多说,我们开始。

const or let

这个问题其实也没什么好争论的,只不过我们可以更好的使用它们:

const :当你这个变量在后续不会发生变量的时候就应该使用它,即使是一个对象也不例外,最明显的一个好处就是别人一看代码就知道这个变量是不可能改变的。

let:这个就更不用说了,当你找不到理由使用 const 的时候就使用它吧。

巧用短路运算符

我们可以会写过类似这样的代码:

// 优化前
function fn(a){
  if(!a){
    return "defaultVlue"
  }else{
    return a
  }
}

但我们可以用短路运算符来简化上面的代码,并且效果不变:

// 优化后
function fn(a){
  return a || "defaultVlue"
}

多用临时变量

比如有如下一段代码:

// 优化前
let person = [
  {
    name: "a",
    age: 11,
    hobby: "basketball"
  },{
    name: "b",
    age: 12,
    hobby:"football"
  }
]

for(let i=0; i<person.length; i++){
  const who = "我是" + person[i].name + "今年" + person[i].age + "喜欢" + person[i].hobby;
}

上面的代码我觉得上面的 for 循环至少有两个地方可以做下优化:获取数组的长度,和在循环中的属性读取

// 优化后
const len = person.length;
for(let i=0; i<len; i++){
  const item = person[i];
  const who = "我是" + item.name + "今年" + item.age + "喜欢" + item.hobby;
}

代码看起来更简洁,理论上程序的性能也得到了提升。

无谓的 else

if...else 这个逻辑判断太常用的,但很多时候我们却部是按部就班

// 优化前
if(!str){
  return false;
}else{
  // ......
}

虽然逻辑很清晰了,但不够简洁,我们可以:

// 优化后
if(!str){
  return false;
}
// ......

不管 return 后面带不带值,我们都可以这样写。

ES6 时代,请忘掉 arguments

在函数中我们有时会用到 arguments 变量 ,获取获取函数的所有参数,如下:

// 优化前
function fn(){
  console.log(arguments);
}

但 ES6 中为我们提供了 ... 扩展运算符,我们没有理由不使用它:

// 优化后
function fn(...rest){
  console.log(rest);
}

rest 变量可以随意,关键是相对于 arguments 这个类数组来说, rest 是一个真正的数组,操作起来更加方便。

题外话,我们甚至可以用 ... 来复制一个数组(浅拷贝):

const arr = [1,2,3,4,5]
const newArr = [...arr]

巧用 ES6 中的对象新特性

在给对象定义一系列方法时,我们很容易的就写出了以下代码:

// 优化前
const hasPermission = {
  add: key => 'add' === key,
  edit: key => 'edit' === key,
  delete: key => 'delete' === key
}
hasPermission.add('add'); // true

但上面的代码有点粗糙,虽然看起来很简洁。如果这个对象里的方法数量是可增减的,后续可能会给你添加方法,也有可能删掉一些方法,不管怎样,你都觉得有点多余不是吗?

在 ES6 中定义属性可以使用[变量名],于是我们的代码就可以优雅得不像样:

// 优化后
const fnNames = ['add','edit','delete']
const hasPermission = {}
fnNames.forEach((item)=>{
  hasPermission[item] = key => item === key
})
hasPermission.add('add'); // true

如果需要添加更多判断方法,我们只需要在 fnNames 数组中添加对应的字符串就可以了。代码会自己为我们生成方法。

当然方法实现很有可能比例子中的复杂得多,这里只是举例说明。

多用箭头函数

// 优化前
const fn = function (a, b){
  return a + b
}

但我们可以通过箭头函数来让代码变得更简洁

// 优化后
const fn = (a, b)=> a + b

不过,只有当代码块部分为一条语句我们才可以这样简写,否则还是需要按旧套路,加上大括号,并带上 return 关键字。箭头函数的这种简写还是很实用的,再简单举个例子:

// 优化前
const arr = [1, 2, 3]
arr.map(function (item) {
  return item * 5
})

上面的回调函数可以使用箭头函数的写法

// 优化后
arr.map(item=>item * 5)

代码美不胜收。

数组 length 判断 0 不要

有时我们会这样写

if(arr.length === 0){
  // ...
}else{
  // ...
}

但我们其实可以更加简洁

if(arr.length){
  // ...
}else{
  // ...
}

只不过 if...else 中的逻辑代码位置要对调下。长度为零则为假,否则为真。