JavaScript进阶(二)
1、数组和对象的解构赋值
`数组解构赋值`
let [a,b,c] = [1,2,3]; // a: 1, b: 2, c: 3
;(([a,b,c]) => console.log(a,b,c))([4, 5, 6]) // 4, 5, 6
`对象解构赋值`
let {uname, age} = {uname:'刘能', age:55} // uname: 刘能, age: 55。注意:等号左边的变量名可以任意顺序,但不能任意名称
;(({uname, age}) => console.log(uname, age))({uname:'赵四', age:56}) // 赵四,56
2、展开运算符在数组中的三个作用
let arr = [2, 5, 8, 0];
// 1)浅拷贝
let arr1 = [...arr];
// 2)剩余参数
function fn(a, b, ...agu){
console.log(agu); // [8, 0, 3, 6, 9]
}
fn([2, 5, 8, 0, 3, 6, 9])
// 3)合并数组
let arr2 = [...arr, ...arr1, 5, '春风']
3、展开运算符在对象中的两个作用
let obj = {
uname: '刘能',
age: 55,
hobby: ['快板', '跳舞'],
}
// 1)浅拷贝
let obj1 = {...obj};
// 2)合并对象
let obj2 = {...obj, ...obj1};
// 注意:如果后一个属性名跟前一个一样时,合并时,后面的会覆盖前面的
4、普通字符串和模板字符串在语法上的区别
// 普通字符串
// 变量和字符串之间用+链接,换行用\n
let uname = '刘能', desc = '象牙山小诸葛';
let str = '我叫' + uname + ',\n人称' + desc;
// 模板字符串
// 更优雅,支持换行,变量直接写在模板占位符${}里面
let uname = '赵四', desc = '亚洲舞王';
let str = `我叫${uname},
人称&{desc}`
5、对象可以简写的两个地方
1、如果属性名和属性值相同,保留一个即可
2、方法可以直接省略
:function
6、es6的类声明属性、原型方法和静态方法的语法
class Father{
// 属性放在构造器里面
constructor(参数1, 参数2, 参数3...){
this.参数1 = 参数1;
this.参数2 = 参数2;
this.参数3 = 参数3;
}
// 原型方法,直接写在构造函数里面
fn(){}
// 静态方法,用static关键字来声明,只有类自己可以使用,不能共享,不能被继承
static fn1(){}
}
7、es6继承的语法
// 父构造函数
class Father{
// 属性放在构造器里面
constructor(参数1, 参数2, 参数3...){
this.参数1 = 参数1;
this.参数2 = 参数2;
this.参数3 = 参数3;
}
// 原型方法,直接写在构造函数里面
fn(){}
// 静态方法,用static关键字来声明,只有类自己可以使用,不能共享,不能被继承
static fn1(){}
}
// 子构造函数,通过extends关键字来继承
class Son extends Father{
constructor(参数1, 参数2, 参数3...){
// 属性的继承:将属性写在super方法里
super(参数1, 参数2, 参数3...);
// 先继承再自有
this.参数4 = 参数4;
}
}
// 方法的继承:使用了extends关键字后父构造函数的原型方法会自动继承
8、es6模块化的两种书写方式
// 1、分别导出,在需要导出的标识符前加上export关键字
export function fn(){}
export let uname = 'xxx';
// 导入:用import关键字导入,可以用解构的方式接收
import {uname, fn} from '需要导入的文件名';
// 2、一起导出,用export default{}进行导出
let str = '赵四';
function show(){};
export default{
str,
show
}
// 导入:用import关键字导入,不可以用解构的方式接收,只能定义一个变量名来接收
import a from '需要导入的文件名'
`注意:在页面导入模块化的js文件时,需要在script标签上添加"type='module'"属性,表示导入的是一个模块化文件`
9、同步和异步的概念
同步:js代码从上往下一步步执行,上面的没有执行完就不会执行下面的,会造成代码阻塞
异步:js代码从上往下执行,碰到异步,将其放在最后,等待所有的同步代码执行完毕后再执行异步
10、异步的三种情况
1、定时器的回调函数
2、事件里面的回调函数
3、ajax的回调函数
11、利用回调地狱解决ajax请求响应顺序不可控的问题
回调地狱:后一个接口的请求需要依赖前一个接口的结果,将后面的接口依次嵌套到前一个接口中,这种套娃现象就是’回调地狱’
// 1、注册
axios.post('url', {
account: "123",
password: "789"
}).then(res => {
console.log('接口一', res);
// 2、检测账号是否存在
axios.post('url1', {
account: res.data.errno
}).then(res => {
console.log('接口二', res);
// 3、登录
axios.post('url2', {
account: res.data.errno,
password: res.data.errno
}).then(res => {
console.log('接口三', res);
}).catch(err => {
console.log(err);
})
}).catch(err => {
console.log(err);
})
}).catch(err => {
console.log(err);
})
12、Promise的作用和基本语法
作用:解决回调地狱的问题
语法:用new关键字实例化,需要传一个函数参数,函数参数里面也需要两个函数参数,一个是resolve,一个是reject
13、Promise实例化过程中的三种状态
1、默认值:pending进行中
2、调用resolve()方法,将pending修改为fulfilled已成功
3、调用reject()方法,将pending修改为rejected已失败
14、Promise实例化过程中resolve和reject的作用
resolve:将pending进行中的状态修改为fulfilled已成功,并且调用then方法,顺带将参数一起传过去
reject:将pending进行中的状态修改为rejected已失败,并且调用catch方法,顺带将参数一起传过去
15、Promise原型方法then、catch和finally的作用
then:Promise状态为已成功时会调用then方法,会返回一个新的Promise实例对象
catch:Promise状态为已失败时会调用catch方法
finally:不论成败,只要Promise状态发生改变就会调用该方法
16、Promise静态方法all、any和race的作用
all:等到所有的Promise都执行成功时就会触发,如果有失败的,就会执行失败的那个Promise
使用场景:用户注册账号时,需要将所有的信息都填写完整,才能注册成功,否则就返回那个错误的Promise
any:只要有一个Promise执行成功就会触发,如果全部失败就会报错
使用场景:在一些极端情况下,比如网络环境差,会同时发送多个相同请求来完成一件事,只要有一个成功了,就会实现功能
race:不论成败,只要有一个Promise执行完毕就立即触发
17、Promise解决回调地狱的原理
Promise实例对象的then方法必须在实例化的时候调用resolve,才会触发,基于此,我们可以在前一个请求的回调函数中将结果resolve出去,再在下一个then方法中发送第二个请求
18、async和await关键字的作用和语法
async:声明一个函数中含有异步代码
语法:放在函数标识符之前
await:等待异步操作执行完成
语法:一般和Promise连用,放在Promise实例对象的前面
19、使用async和await解决回调地狱
async function fn(){
let res = await axios.post('url', data);
let res2 = await axios.post('url2', res);
let res3 = await axios.post('url3', res2);
console.log('结果是' + res3);
}
fn();