摘自:你会用ES6,那倒是用啊! - 掘金
一、关于取值
取值在程序中非常常见,比如从对象obj
中取值。
const obj = {
a:1,
b:2,
c:3,
d:4,
e:5,
}
常规取值:
方法一:
const a = obj.a;
const b = obj.b;
const c = obj.c;
const d = obj.d;
const e = obj.e;
方法二:
const f = obj.a + obj.d;
const g = obj.c + obj.e;
吐槽:“不会用ES6的解构赋值来取值吗?5行代码用1行代码搞定不香吗?直接用对象名加属性名去取值,要是对象名短还好,很长呢?搞得代码中到处都是这个对象名。”
改进:
const {a,b,c,d,e} = obj;
const f = a + d;
const g = c + e;
反驳
不是不用ES6的解构赋值,而是服务端返回的数据对象中的属性名不是我想要的,这样取值,不是还得重新创建个遍历赋值。
吐槽
看来你对ES6的解构赋值掌握的还是不够彻底。如果想创建的变量名和对象的属性名不一致,可以这么写:
const {a:a1} = obj;
console.log(a1);// 1
补充
ES6的解构赋值虽然好用。但是要注意解构的对象不能为undefined
、null
。否则会报错,故要给被解构的对象一个默认值。
正确写法:
const {a,b,c,d,e} = obj || {};
错误写法:
const obj = null
const {a,b,c,d,e} = obj;
console.log(d);
控制台报错:
二、关于合并数据
比如经常遇到的合并两个数组,合并两个对象。
const a = [1,2,3];
const b = [1,5,6];
const c = a.concat(b);//[1,2,3,1,5,6]
const obj1 = {
a:1,
}
const obj2 = {
b:1,
}
const obj = Object.assign({}, obj1, obj2);//{a:1,b:1}
吐槽
ES6的扩展运算符是不是忘记了,还有数组的合并不考虑去重吗?
改进
const a = [1,2,3];
const b = [1,5,6];
const c = [...new Set([...a,...b])];//[1,2,3,5,6]
const obj1 = {
a:1,
}
const obj2 = {
b:1,
}
const obj = {...obj1,...obj2};//{a:1,b:1}
在合并数组中发现
const c = [...new Set([...a,...b])];//[1,2,3,5,6]
...new Set([ ]) 这是什么呢,难道直接[...a,...b]不能合并吗?
const a = [1,2,3];
const b = [1,5,6];
const c = [...a,...b]
console.log(c) // [1, 2, 3, 1, 5, 6]
代码验证是可以合并的,但是并不能去重,所以...new Set([ ])是用来去重的
ES6提供了新的数据结构Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
Set本身是一个构造函数,用来生成Set数据结构。
语法:...new Set(arr)
param:arr:要拷贝的值
结果值:拷贝了arr,并且也去除了重复的值
此方法只使用于过滤基本数据类型:string, number, boolean, null, undefined
三、关于拼接字符串
const name = '小明';
const score = 59;
let result = '';
if(score > 60){
result = `${name}的考试成绩及格`;
}else{
result = `${name}的考试成绩不及格`;
}
吐槽
像你们这样用ES6字符串模板,还不如不用,你们根本不清楚在${}
中可以做什么操作。在${}
中可以放入任意的JavaScript表达式,可以进行运算,以及引用对象属性。
改进
const name = '小明';
const score = 59;
const result = `${name}${score > 60?'的考试成绩及格':'的考试成绩不及格'}`;
四、关于if中判断条件
if(
type == 1 ||
type == 2 ||
type == 3 ||
type == 4 ||
){
//...
}
吐槽
ES6中数组实例方法includes
会不会使用呢?
改进
const condition = [1,2,3,4];
if( condition.includes(type) ){
//...
}
拓展一下吧,知识总是不嫌多的
Array.prototype.includes方法返回一个布尔值,表示某个数组是否包含给定的值,与字符串的includes方法类似。ES2016引入了该方法。
[1, 2, 3].includes(2) // true
[1, 2, 3].includes(4) // true
[1, 2, NaN].includes(NaN) // true
该方法的第二个参数表示搜索的起始位置,默认为0。如果第二个参数为负数,则表示倒数的位置,如果这时它大于数组长度(比如第二个参数为-4, 但数组长度为3),则会重置为0开始。
[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true
没有该方法之前,我们通常使用数组的indexOf方法,检查是否包含某个值。
if (arr.indexOf(el) !== -1) {
// ...
}
indexOf方法有两个缺点,一是不够语义化,它的含义是找到参数值的第一个出现位置,所以要去比较是否不等于-1,表达起来不够直观。二是,它内部使用严格相等运算符进行判断,这会导致对NaN的误判。
[NaN].indexOf(NaN) // -1
includes使用的是不一样的判断算法,就没有这个问题。
[NaN].includes(NaN) // true
另外,Map和Set数据结构有一个has方法需要注意与includes区分。
Map结构的has方法,是用来查找键名的,比如Map.prototype.has(key),
WeakMap.prototype.has(key), Reflect.has(target, propertyKey)
-Set结构的has方法,是用来查找值的,比如Set.prototype.has(value),
WeakSet.prototype.has(value)
搬运自https://www.jb51.net/article/184979.htm 我是知识 的搬运工哈哈
结束结束,下一项
五、关于列表搜索
在项目中,一些没分页的列表的搜索功能由前端来实现,搜索一般分为精确搜索和模糊搜索。搜索也要叫过滤,一般用filter
来实现。
const a = [1,2,3,4,5];
const result = a.filter(
item =>{
return item === 3
}
)
吐槽
如果是精确搜索不会用ES6中的find
吗?性能优化懂么,find
方法中找到符合条件的项,就不会继续遍历数组。
改进
const a = [1,2,3,4,5];
const result = a.find(
item =>{
return item === 3
}
)
六、关于扁平化数组
一个部门JSON数据中,属性名是部门,属性值是个部门成员id数组集合,现在要把有部门的成员id都提取到一个数组集合中。
const deps = {
'采购部':[1,2,3],
'人事部':[5,8,12],
'行政部':[5,14,79],
'运输部':[3,64,105],
}
let member = [];
for (let item in deps){
const value = deps[item];
if(Array.isArray(value)){
member = [...member,...value]
}
}
member = [...new Set(member)]
这个代码感觉已经很好了,可是还是有吐槽呀,真是代码无止尽呀
吐槽
获取对象的全部属性值还要遍历吗?Object.values
忘记了吗?还有涉及到数组的扁平化处理,为啥不用ES6提供的flat
方法呢,还好这次的数组的深度最多只到2维,还要是遇到4维、5维深度的数组,是不是得循环嵌套循环来扁平化?
改进
const deps = {
'采购部':[1,2,3],
'人事部':[5,8,12],
'行政部':[5,14,79],
'运输部':[3,64,105],
}
let member = Object.values(deps).flat(Infinity);
其中使用Infinity
作为flat
的参数,使得无需知道被扁平化的数组的维度。
补充
flat
方法不支持IE浏览器。IE要退出历史舞台喽
哇,果然一行就搞定了耶,可是是啥意思呢,还是继续学习吧
先打印一下看看
const deps = {
'采购部':[1,2,3],
'人事部':[5,8,12],
'行政部':[5,14,79],
'运输部':[3,64,105],
}
let member = Object.values(deps);
console.log(member)
在打印下
console.log(member.flat(Infinity)) //[1, 2, 3, 5, 8, 12, 5, 14, 79, 3, 64, 105]
数组没有去重吧,不过也简单,加上上面的去重...new Set([ ])就好了
拓展拓展,学习
Object.keys()
:获取对象的键,es6之前就有的方法;Object.values()
:获取对象的值,es6新增方法;Object.entries()
:获取对象的键与值,es6新增方法。
const person = {
name: 'Jae',
age: 22
};
cnosole.log(Object.keys(person)); // ["name", "age"]
cnosole.log(Object.values(person)); // ["Jae", 22]
cnosole.log(Object.entries(person)); // [["name", "Jae"], ["age", 22]]
七、关于获取对象属性值
const name = obj?.name;
吐槽
ES6中的可选链操作符会使用么?
改进
const name = obj?.name;
八、关于添加对象属性
当给对象添加属性时,如果属性名是动态变化的,该怎么处理。
吐槽
为何要额外创建一个变量。不知道ES6中的对象属性名是可以用表达式吗?
改进
let obj = {};
let index = 1;
obj[`topic${index}`] = '话题内容';
九、关于输入框非空的判断
在处理输入框相关业务时,往往会判断输入框未输入值的场景。
if(value !== null && value !== undefined && value !== ''){
//...
}
吐槽
ES6中新出的空值合并运算符了解过吗,要写那么多条件吗?
if((value??'') !== ''){
//...
}
空值合并操作符(??
)是一个逻辑操作符,当左侧的操作数为 null 或者 undefined 时,返回其右侧操作数,否则返回左侧操作数。
const foo = null ?? 'default string';
console.log(foo); //default string
const baz = 0 ?? 42;
console.log(baz); //0
十、关于异步函数
异步函数很常见,经常是用 Promise 来实现。
const fn1 = () =>{
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1);
}, 300);
});
}
const fn2 = () =>{
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(2);
}, 600);
});
}
const fn = () =>{
fn1().then(res1 =>{
console.log(res1);// 1
fn2().then(res2 =>{
console.log(res2)
})
})
}
吐槽
如果这样调用异步函数,不怕形成地狱回调啊!
改进
const fn = async () =>{
const res1 = await fn1();
const res2 = await fn2();
console.log(res1);// 1
console.log(res2);// 2
}
补充
但是要做并发请求时,还是要用到Promise.all()
。
const fn = () =>{
Promise.all([fn1(),fn2()]).then(res =>{
console.log(res);// [1,2]
})
}
如果并发请求时,只要其中一个异步函数处理完成,就返回结果,要用到Promise.race()
。