『简单易懂』编程风格最佳实践

223 阅读4分钟

前言

本文旨在讨论将es6的语法运用到编程实践中,与传统的JavaScript一起写出合理、易读、维护性高的代码。

不涉及对错,不涉及价值观。如果您觉得可以吸收采纳,请给我一点鼓励。

如果有优化的地方,请在评论跟我联系,我会修正。谢谢

块级作用域

在函数式声明时,我们最好摒弃var声明而使用let,因为let并没有副作用

function fn(){
   console.log(a) //ReferenceError
   let a =2
}

上面的代码如果换成var则会打出undefined,原因是var有变量提升,而这样的方式违背了先声明后使用的原则

全局常量和线程安全

letconst之间,我们应当优先使用const,尤其在全局环境中,不应设置变量,更应该设置常量。

const优于let的原因:

1、const的语音易读,且告诉阅读代码的人,这个数据不可变

2、符合函数式编程的思想:运算不应修改,而应当新建值。

3、编译器对const有优化效果

4、防止无意间修改变量引发错误

// bad
let a =1
let b =2
let c =3

//better
const a=1
const b=2
const c=3

//best
const [a,b,c]=[1,2,3]

字符串

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

动态字符串一律使用反引号

//bad
const a = "foobar" 

//better
const a='foobar' 

// best
const c=`foo${a}bar`

解构赋值

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

const arr=[1,2,3,4]
// bad
const a=arr[0]

//better
const [a]=arr

//best
const [a,...b]=arr

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

function fn({x,y}){
   console.log(x,y)
}
fn({x:1,y:2})

如果函数有多个返回值,那么优先使用对象的解构赋值接收而不是数组,这样便于以后添加返回值,以及返回值的顺序

//bad
function fn(){
   return [1,2]
}
const [x,y]=fn()

//best
function fn(){
   return {x:1,y:2}
}
const {x,y}=fn()

对象

单行定义的对象,最后一个成员不以逗号结尾

多行定义的对象,最后一个成员以逗号结尾

const a={x:1,y:2}
const b={
   x:1,
   y:2,
   c:3,
}

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

//better
const obj={a:1,b:2}
Object.assign(obj,{c:3})

// best
const obj={
   a:1,
   b:2,
   c:null,
}
obj.c=3

如果对象的属性名是动态的,可以在创建对象时使用属性表达式

const obj={
   a:1,
   b:2,
   [getC(3)]:3,
}

对象的属性和方法,尽量使用简洁表达法

//bad
const o={
   ref:ref,
   add:function(){},
}

//best
const o={
   ref,
   add(){}
}

数组

使用扩展运算符来拷贝数组

// bad
const a=[1,2,3,4].slice()

//best
const c=[1,2,3,4]
const a=[...c]

如果遇到伪数组,那么请使用Array.from()转成数组

function fn(){
   const arg=Array.from(arguments)
   return arg
}
fn(1,2,3,4)

函数

立即执行函数写成箭头函数

(()=>{
   console.log(12)
   }
)()

在使用匿名函数当参数的场合,尽量使用箭头函数来代替

//bad
[1,2,3].forEach(function(value){
   console.log(value)
})

//best
[1,2,3].forEach((value)=>{
   console.log(value)
})

不要在函数内使用arguments变量,而应当使用...rest运算符,这样可以显式声明我们想要获取参数来使用,且可以提供一个真正的数组

//bad
function fn(){
   const rest= Array.from(arguments)
   return rest.map((v)=>{
      return v * 2
   })
}

// best
function fn(...rest){
  return rest.map((v)=>{
      return v * 2
   })
}
fn(1,2,3)

使用默认值语法来设置函数参数的默认值

function fn(a,b=1){
   console.log(a,b)
}
fn(1) //1 1

Map

如果我们需要做表结构编程,比如键值对的数据解构,最好是使用Map解构而尽量少用object对象的结构。因为Map方法自带遍历方法,比如forEach,且数据解构更加丰富,object对象的键只能是字符串,而Map的键可以是任意数据类型。

let map = new Map(arr);

for (let key of map.keys()) {
  console.log(key);
}

for (let value of map.values()) {
  console.log(value);
}

for (let item of map.entries()) {
  console.log(item[0], item[1]);
}

模块

坚持标准写法,使用import、export。

如果模块只有一个输出,那么使用export default

如果模块不仅仅只有一个输出,那么不要使用export defaultexportexport default不要同时使用。

不要在模块输入中使用通配符,这样可以确保模块中至少有一个默认输出export default

// bad
import * as default from './index.tsx'

//best 
import default from './index.tsx'

如果模块默认输出一个函数,函数名的首字母应该小写。

function makeStyleGuide() {
}

export default makeStyleGuide;

如果模块默认输出一个对象,对象名的首字母应该大写。

const StyleGuide = {
  es6: {
  }
};

export default StyleGuide