导读:平时我们在开发中,为了赶时间尽快完成项目而习惯采用我们之前啰嗦的写法来实现某些功能,没有去思考有没有更好的实现方式,我们仿佛真的成了一个没有灵魂的机器。
有时候你是不是会听到:
“因为时间太紧了,先把功能实现,后面有时间再优化代码”
这种情况下往往就没有下文了,正所谓:
“Later is Never”
长年累月就会发现项目中的代码写得很“糙”。
本文旨在使用 ES6 语法优化代码中的一些小功能点,ES6 中的一些新特性确实能给我们提供一些很好的帮助,使我们的代码更简洁和易读。相信大家对 ES6 并不陌生,官方文档都看了至少一遍了吧,下面就看一下如何使用 ES6 将我们的代码变得更美观。
01
对象取值
const obj= {
firstName: "an",
lastName: "xiu",
gender: "female",
age: 18
ES5 写法:
const firstName = obj.firstName
const lastName = obj.lastName
const gender = obj.gender
const age = obj.age
这样一个个定义变量和取值有点繁琐,我们可以使用 ES6 对象的解构赋值尝试一下。
ES6 写法:
const { firstName, lastName, gender, age } = obj;
一行代码搞定!!!
如果我们想要定义的变量和对象中的字段名不同,我们还可以这样做。
const { firstName: stuFirstName, lastName: stuLastName, gender: stuGender, age: StuAge } = obj; console.log(stuFirstName) // 1
这里需要注意的是:
const { firstName: stuFirstName } = obj
其中 stuFirstName 为我们新定义的变量,firstName 为从对象中取出的变量,顺序与我们平时赋值的写法正好相反,我们可以将其理解为:a as a1给予 a 一个 a1 的别称。
02
数组合并
const arr1 = [1,2,3];
const arr2 = [1,4,5];
ES5 写法:
const arr = arr1.concat(arr2); // [1,2,3,1,4,5]
使用 concat() 可以将两个数组拼接成一个新数组,但是我们漏掉了一个点,生成的新数组包含重复的元素,我们并没有对数组进行去重操作。
ES6 写法:
ES6提供了新的数据结构Set,它类似于数组,但是成员的值是唯一的,没有重复的值。
基于以上合并数组的操作,对数组进行去重。
const newArr = [...new Set(arr)];
或
const newArr = Array.from(new Set(arr)) // [1,2,3,4,5]
03
if 条件判断
当我们一个 if 语句中需要对一个变量进行多个值的判断时,我们是这样写的:
ES5 写法:
if (type === 1 || type === 2 || type === 3 || type === 4) {
// 逻辑处理
}
ES6 写法:
ES6 提供了 includes() 函数,用来表示某个数组是否包含给定的值。所以我们可以这样写:
const conditions = [1,2,3,4]
if (conditions.includes(type)) {
// 逻辑处理
}
这样是不是简单了很多。当然在没有 includes() 之前我们也可以使用 indexOf() 进行判断,两者都会遍历数组来查找元素,但还是有一些细微的差别:
语义化:
indexOf() 返回的是元素第一个出现的索引值,如果我们要判断元素是否存在,还需要去比较返回值是不是等于 -1 ,这样不够语义和直观;而 includes() 直接返回 true 或 false 表示该元素是否在数组中。
对 NaN 值的处理:
indexOf() 内部使用严格相等运算符进行判断,使得对 NaN 的判断不准确。
[NaN].indexOf(NaN) // -1
[NaN].includes(NaN) // true
04
获取对象的属性值
在 js 中我们经常会需要获取对象的某个属性,但是我们往往首先需要判断一下属性的上层对象是否存在。
比如我们要读取 studentInfo.oldStudent.address.city。
ES5 写法:
// 错误写法
const city = studentInfo.oldStudent.address.city || '';
// 正确写法
const city = (studentInfo && studentInfo.oldStudent && studentInfo.oldStudent.address && studentInfo.oldStudent.address.city) || '';
由于 city 属性嵌套较深,在最外层对象的第四层,所以需要判断四次,每一层是否有值,这种方法显而易见的繁琐,表达还不够清晰。
ES6提供链判断运算符(?.)可以判断对象是否存在。
上面代码我们使用链判断运算符可以这样写:
const city = studentInfo?.oldStudent?.address?.city || '';
使用链判断运算符的方法当运算符左侧的对象为 null 或 undefined 时,就不会再往下运算了,直接返回我们设置的默认值 。
05
数组展开
const arr = ['cat', ['lion', 'tiger']]
ES5 写法:
function flatten(arr) {
let result = [];
for (let i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
result = result.concat(flatten(arr[i]));
} else {
result.push(arr[i]);
}
}
return result;
}
这种方法确实可以,那么我们可以想想更简单的方法,或许我们是不是还记得数组的 reduce() 方法的使用呢。
reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。
那么我们使用 reduce() 方法展开数组。
const flat = arr => arr.reduce((pre,cur) =>(Array.isArray(cur) ? [...pre,...flat(cur)] : [...pre,cur]), [])
flat(['cat', ['lion', 'tiger']]); // ['cat', 'lion', 'tiger']
其实 ES6 还为我们提供了 flat() 方法,目的就是用来将嵌套的数组“拉平”,这个方法会返回一个新数组,对原数组没有影响。
['cat', ['lion', 'tiger']].flat() // ['cat', 'lion', 'tiger']
但是,需要注意的是:
flat() 默认只会展开一层,如果想要展开多层的嵌套数组,需要为 flat() 提供一个参数用来表示想要展开的层数,默认为 1 。
['cat', ['lion', 'tiger',['dog']]].flat() // ['cat', 'lion', 'tiger', ['dog']]
['cat', ['lion', 'tiger',['dog']]].flat(2) // ['cat', 'lion', 'tiger', 'dog']
如果我们不知道数组有几层或不管有多少层嵌套,都要转成一维数组,可以用 Infinity 关键字作为参数。
['cat', ['lion', 'tiger',['dog']]].flat(Infinity) // ['cat', 'lion', 'tiger', 'dog']
05
结尾
以上只是列举了我在项目中遇到的几个场景,对于代码的优化需要我们在一点一滴的细节中开始。我们真的应该花点时间静下心来多思考,代码才能越写越好,一个优美的代码不单单减少我们的开发量、提高开发效率,更能以清晰明了的方式展示给其他阅读者,增强可读性。
最后,以一个小优化题目结束。
ignoreProductFilter() {
const list = []
products.forEach((item) => {
if (!ignoreList.includes(item.skuId)) {
list.push(item)
}
})
return list
}
动动你的小脑袋优化一下吧(函数内的代码用一行搞定)。