变量的解构赋值
数组
以前,为变量赋值,只能直接指定值:
let a = 1;
let b = 2;
、、、、
但现在,es6允许我们写成这样:
let [a,b] = [1,2];
//a:1;
//b:2;
上面的代码表示,在数组中,可以按照对应的位置,为变量进行赋值。不过需要注意一点的是:等号两边的模式需要相同。下面是一些例子
let [foo, [[bar], baz]] = [1, [[2], 3]];
foo // 1
bar // 2
baz // 3
let [ , , third] = ["foo", "bar", "baz"];
third // "baz"
若等号两边模式不同,结构不成功,变量的值为Undefined。
let [foo] = [];
let [bar, foo] = [1];
//以上两个赋值都不成功,foo的值都为undefined
对象
取值在我们编程中非常常见,比如从对象obj中取值。
const obj = { a:1, b:2, c:3};
、、、
const a = obj.a;
const b = obj.b;
const c = obj.c;
但是这样大家有没有发现,简单的取对象中的三个变量值,就需要三行代码实现。若使用结构赋值的话,我们只需要一行就可以解决;
const {a,b,c} = obj;
//a:1
//b:2
//c:3
对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。那么可能大家会考虑到一个问题,如果服务端返回的属性名不是我想要的,那么结果赋值不是也麻烦吗?不用担心,我们可以这样实现。如果服务端返回的属性名是a,而我们使用时需要用的属性名为b。那么我们就可以这样定义:
const {a:b} = obj;
//b:1
解构失败,变量的值也为undefined。
let {foo} = {a:1};
//foo:undefined
数据合并:主要对拓展运算符的使用
数组
之前合并两个数组,我们一般会用以下方法实现:
const a = [1,2,3];
const b = [1,5,6];
const c = a.concat(b);//[1,2,3,1,5,6]
若使用es6语法,我们可以这样实现:
const c = [...a,...b];//[1,2,3,4,5,6]
不过需要注意的是,这两种方法实现的都只是浅拷贝,使用的时候需要注意。
对象
关于对象的合并,我们之前常用的方法是:
const obj1 = { a:1};
const obj1 = { b:1};
const obj = Object.assgin({}, obj1, obj2);//{a:1,b:1}
若使用es6语法,我们可以这样实现:
const obj = {...obj1,...obj2};
//obj:{a:1,b:2}
模板字符串
这边我们举一个例子。
const name = 'ac';
const score = 79;
let result = '';
let desc = '的考试成绩'
if(score > 60){
result = `${name}${desc}及格`;
}else{
result = `${name}${desc}不及格`;
}
是不是看起来就觉得很麻烦。我们再来看一个例子。
const name = 'ac';
const score = 100;
const result = `${name}${score > 60?${desc}'合格':${desc}'不合格'}`;
这样看起来是不是方便多了。 es6中增加了对模板字符串的使用。在{}内可以放入任意的 JavaScript 表达式,可以进行运算,以及引用对象属性。
数组常用的扩展方法
includes
该方法返回一个布尔值,表示某个数组是否包含给定的值。
[1,2,3].includes(1);//true
[1,2,3].includes(4);//false
该方法的第二个参数表示搜索的起始位置,默认为0。如果第二个参数为负数,则表示倒数的位置,如果这时它大于数组长度(比如第二个参数为-4,但数组长度为3),则会重置为从0开始。
[1,2,3].includes(3,3);//false
[1, 2, 3].includes(3, -1); // true
利用该方法可以优化if判断语句。我们常常一个判断语句中需要判断多个值,我们可能会这样去判断:
if(
type == 1 ||
type == 2 ||
type == 3 ||
type == 4
){
//...
}
这样是不是看起来特别麻烦,如果用了includes方法,我们可以优化为:
let condition = [1,2,3,4];
if(condition.includes(type)){}
find()
数组实例的find方法,用于找出第一个符合条件的数组成员。它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为true的成员,然后返回该成员。如果没有符合条件的成员,则返回undefined。
const demo = [1,2,3,4,5];
demo.find((n) => n > 4);//5
关于find方法在项目中的运用。
在项目中,一些没分页的列表的搜索功能由前端来实现,搜索一般分为精确搜索和模糊搜索。搜索也要叫过滤,一般我们可以用filter来实现。
const a = [1,2,3,4,5];
const result = a.filter( item =>{ return item === 3 } )
考虑到性能优化问题,我们一般选用find方法,一旦找到符合条件的数据时,便不会继续便利数组。
const a = [1,2,3,4,5];
const result = a.find( item =>{ return item === 3 } )
flat()
我们先看一个例子: 一个部门JSON数据中,属性名是部门id,属性值是个部门成员id数组集合,现在要把有部门的成员id都提取到一个数组集合中。是不是还在考虑通过遍历最后再去重去实现吗?
const deps = {
'事业部':[1,2,3],
'人事部':[4,8,12],
'财务部':[9,14,79]}
let member = [];
for (let item in deps){
const value = deps[item];
if(Array.isArray(value)){
member = [...member,...value] }
}
//member:[1,2,3,4,8,12,9,14,79]
但如果我们用flat方法去实现,会发现方便很多;
const deps = {
'事业部':[1,2,3],
'人事部':[4,8,12]
}
const menber = Object.values(deps).flat();//[1,2,3,4,8,12]
数组的成员有时是数组,flat()方法用于将嵌套的数组“拉平”,变成一维的数组。该方法返回一个新数组,对原数据没有影响。默认flat()方法只会拉平一层,若想要拉平多层,可以传入一个指定参数。如flat(2);
let demo = [1,[[2,3],4];
demo.flat(2);//[1,2,3,4]
如果不管有多少层嵌套,都要转成一维数组,可以用Infinity关键字作为参数。
[1, [2, [3]]].flat(Infinity)
// [1, 2, 3]
获取对象属性值
我们要获取一个对象属性值,首先需要去判断这个对象是否存在,然后再去取。
const name = obj && obj.name;
如果嵌套层级太多的话,相应的判断条件就会很多,使用起来查阅起来都不方便。我们可以使用es6中的可选链操作符去获取。
const name = obj?.name
对象的属性名表达式
定义对象属性有两种方法:
const obj = {
foo:true,
name:'ac'
}
obj.age = 25;//1
obj['a' + 'b'] = '123';//2
若属性名是动态变化的,第一种方法显然无法实现。对象的属性名表示式就很好的为我们解决了这个问题。
let obj = {};
let index = 1;
obj[`topic${index}`] = '这是内容';
空值合并运算符
我们在处理输入框相关业务时,往往会判断输入框未输入值的场景。
if(value !== null && value !== undefined && value !== ''){ //... }
使用空值合并运算符,会大大减少判断条件的书写
if(value ?? '' !== ''){
...
}
??:当左侧的操作数为 [null] 或者 [undefined] 时,返回其右侧操作数,否则返回左侧操作数。
异步函数
异步函数很常见,一般用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);//2
})
})
}
如果这样调用异步函数,视觉上看也很吃力。 改进:
const fn = async () =>{
const res1 = await fn1();
const res2 = await fn2();
console.log(res1);// 1
console.log(res2);// 2
}