前言
相信每个前端工程师,或者了解前端的人都知道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 cfor (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而来,虽然文章中很多地方只贴了代码,但是却很容易让人有一针见血的触动,不过个人还是觉得缺少一些必要的说明分析,所以我做了一点补充。