如何正确地使用ES6提高我们的代码质量

前言

相信每个前端工程师,或者了解前端的人都知道ES6。它是js的一次巨变,它为我们开发js前端项目的时候带来了许多更好的去书写代码的方式。但是很多时候我们可能都没有过度地去关注优化代码这一块内容,哪怕有也只是注意到了一些比较大众化,比较常见的东西,比如let和const、箭头函数、解构赋值……。这一篇文章将会简单直观,清晰明了地阐述ES6的一些变革和它们的真正使用方式。

1、 模板字符串

// bad
const foo = 'this is a' + example;

// good
const foo = `this is a ${
      
      example}`;

优点:对比之前能更方便地去拼接字符串,阅读性也更强一些。

2、Symbol

①唯一值

// bad
// 1. 创建的属性会被 for-in 或 Object.keys() 枚举出来
// 2. 一些库可能在将来会使用同样的方式,这会与你的代码发生冲突
if (element.isMoving) {
    
    
  smoothAnimations(element);
}
element.isMoving = true;

// good
if (element.__$jorendorff_animation_library$PLEASE_DO_NOT_USE_THIS_PROPERTY$isMoving__) {
    
    
  smoothAnimations(element);
}
element.__$jorendorff_animation_library$PLEASE_DO_NOT_USE_THIS_PROPERTY$isMoving__ = true;

// better
var isMoving = Symbol("isMoving");

...

if (element[isMoving]) {
    
    
  smoothAnimations(element);
}
element[isMoving] = true;

②魔术字符串

首先需要理解什么是魔术字符串:

魔术字符串指的是在代码之中多次出现、与代码形成强耦合的某一个具体的字符串或者数值。
魔术字符串不利于修改和维护,风格良好的代码,应该尽量消除魔术字符串,改由含义清晰的变量代替。

直接贴代码更直观:

function getResults(param{
    
    
	if(param == 'name'){
    
    
		// ...
	}
}
// 函数中赋值 'name',所以 'name' 这个字符串就是魔术字符串
getResults('name')

那如何去改善,优雅地改动我们的代码,举个栗子。

在这里插入图片描述

3、Set 和 Map

①Set可以常用到的操作:数组去重

[...new Set(array)]

②Map优化条件语句

// 根据颜色找出对应的水果

// bad
function test(color) {
    
    
  switch (color) {
    
    
    case 'red':
      return ['apple', 'strawberry'];
    case 'yellow':
      return ['banana', 'pineapple'];
    case 'purple':
      return ['grape', 'plum'];
    default:
      return [];
  }
}

// good
const fruitColor = {
    
    
  red: ['apple', 'strawberry'],
  yellow: ['banana', 'pineapple'],
  purple: ['grape', 'plum']
};

function test(color) {
    
    
  return fruitColor[color] || [];
}

// better
const fruitColor = new Map([
  ['red', ['apple', 'strawberry']],
  ['yellow', ['banana', 'pineapple']],
  ['purple', ['grape', 'plum']]
]);

对比good,better这种写法是优化了什么?

1.数据结构更清晰:Map不同于Object,它可以直接存储键值对,使得数据的表达更加清晰,避免了对象中存在原型属性和方法带来的干扰。
2.可迭代性更好:Map是一个可迭代的数据结构,所以在遍历Map时可以直接使用for…of循环或者forEach方法进行遍历,避免了使用Object.keys()等方法获取属性名的麻烦。
3.代码性能更高:Map对于大量数据的处理效率要高于对象。

4. for of

for…of 循环可以使用的范围包括:

  • 数组
  • Set
  • Map
  • 类数组对象,如 arguments 对象、DOM NodeList 对象
  • Generator 对象
  • 字符串

ES2015 引入了 for…of 循环,它结合了 forEach 的简洁性和中断循环的能力,简而言之,用for of比 forEach更好

for (const v of ['a', 'b', 'c']) {
    
    
  console.log(v);
}
// a b c

for (const [i, v] of ['a', 'b', 'c'].entries()) {
    
    
  console.log(i, v);
}
// 0 "a"
// 1 "b"
// 2 "c"

5、 Promise

Promise是解决‘先后问题’(需要先得到一个参数才能解决另一件事情的时候)的一个很好的方案。

// bad
request(url, function(err, res, body) {
    
    
    if (err) handleError(err);
    fs.writeFile('1.txt', body, function(err) {
    
    
        request(url2, function(err, res, body) {
    
    
            if (err) handleError(err)
        })
    })
});

// good
request(url)
.then(function(result) {
    
    
    return writeFileAsynv('1.txt', result)
})
.then(function(result) {
    
    
    return request(url2)
})
.catch(function(e){
    
    
    handleError(e)
});

finally,表示无论如何最后都会执行的代码。

fetch('file.json')
.then(data => data.json())
.catch(error => console.error(error))
.finally(() => console.log('finished'));

6、Async

异步解决方案之一,让代码变得更简洁,可以发挥跟promise差不多的作用。错误处理得用try……catch,async和await必须同时存在。

// 例子 8-3

// good
function fetch() {
    
    
  return (
    fetchData()
    .then(value1 => {
    
    
      return fetchMoreData(value1)
    })
    .then(value2 => {
    
    
      return fetchMoreData2(value2)
    })
  )
}

// better
async function fetch() {
    
    
  const value1 = await fetchData()
  const value2 = await fetchMoreData(value1)
  return fetchMoreData2(value2)
};

错误捕获

// 例子 8-4

// good
function fetch() {
    
    
  try {
    
    
    fetchData()
      .then(result => {
    
    
        const data = JSON.parse(result)
      })
      .catch((err) => {
    
    
        console.log(err)
      })
  } catch (err) {
    
    
    console.log(err)
  }
}

// better
async function fetch() {
    
    
  try {
    
    
    const data = JSON.parse(await fetchData())
  } catch (err) {
    
    
    console.log(err)
  }
};

promise和async看情况使用,代码更加优雅。

// bad
(async () => {
    
    
  const getList = await getList();
  const getAnotherList = await getAnotherList();
})();

// good
(async () => {
    
    
  const listPromise = getList();
  const anotherListPromise = getAnotherList();
  await listPromise;
  await anotherListPromise;
})();

// good
(async () => {
    
    
  Promise.all([getList(), getAnotherList()]).then(...);
})();

7、函数

这个不多说了,简单直接,清晰明了。

// bad
function test(quantity) {
    
    
  const q = quantity || 1;
}

// good
function test(quantity = 1) {
    
    
  ...
}

这里有解构赋值的知识点,究极蛇皮有用。 better的写法可以解决不传参会报错的问题。

doSomething({
    
     foo: 'Hello', bar: 'Hey!', baz: 42 });

// bad
function doSomething(config) {
    
    
  const foo = config.foo !== undefined ? config.foo : 'Hi';
  const bar = config.bar !== undefined ? config.bar : 'Yo!';
  const baz = config.baz !== undefined ? config.baz : 13;
}

// good
function doSomething({
    
     foo = 'Hi', bar = 'Yo!', baz = 13 }) {
    
    
  console.log(foo)
}

dosomething(); // 这里会报错,foo没定义

// better
function doSomething({
    
     foo = 'Hi', bar = 'Yo!', baz = 13 } = {
    
    }) {
    
    
  ...
}

以上代码从这位大佬→冴羽的文章copy而来,虽然文章中很多地方只贴了代码,但是却很容易让人有一针见血的触动,不过个人还是觉得缺少一些必要的说明分析,所以我做了一点补充。

猜你喜欢

转载自blog.csdn.net/huangzhixin1996/article/details/130627092