day20 闭包和promise
闭包
概述:
闭包就是在函数内部返回一个函数,内部函数有外部函数的引用,这个结构就叫闭包
函数的生命周期
函数在预编译阶段
开辟一个内存空间
将对应的代码块放到这个内存空间
函数的执行阶段
将对应的函数开辟的这个空间放在执行栈上
执行栈开始执行对应的函数对应空间的代码块
这个代码如果需要开辟空间 它就在这个对应的这个函数的内存空间上开辟
当不需要使用这个函数了 对应的函数的内存空间就会被回收 里面的代码开辟的空间也被回收
如果不想变量被回收 那么可以将这个变量放到引用数据类型里面 保证这个引用数据类型对象的引用 这个时候GC就不会回收对应的变量了
保证某个变量不被回收的机制就叫做闭包(返回一个引用数据类型 这个里面保证对应的对应这个变量的引用 从而不被回收)
闭包的优劣
优势
内部函数拥有外部函数参数和变量的引用 使我们的参数和变量的作用范围被扩大
对应的参数不被回收 再使用的时候就不需要重新开辟空间 速度更快
劣势
内部函数要一直保持对外部函数里面参数和变量的引用
因为不会被回收 所有对应的内存空间会一直占用
闭包的应用
防抖(在规定时间内只执行一次 执行最后一次)
例子:排电梯
functiondebounce(fn,delay) {
vartimer=null
returnfunction() {
clearTimeout(timer)
timer=setTimeout(fn,delay)
}
}
节流 (在规定时间内执行第一次 控制执行次数)
例子:红绿灯
functionthrottle(fn,delay) {
vartimer=null;
returnfunction() {
if(timer)return
timer=setTimeout(()=>{
fn()
timer=null
},delay)
}
}
防抖和节流的区别
防抖执行最后一次 节流执行第一次
在规定时间内 防抖只执行一次 节流减少对应执行次数
防抖对应的开始下一次要先清除上一次 节流开始下一次先要判断上一次是否执行完毕
函数柯里化 (将多个参数的函数拆分为多个单参数的函数 可以自由的组合)
核心就是 参数不够返回对应的函数 参数够了返回结果
Promise
概述:promise是es6新增的一个类 翻译为承诺
有三种状态 等待状态 成功状态 拒绝状态
它被设计为 异步 的 它里面的内容是异步的(方法是异步的)
promise三种状态
等待状态 (没有处理) pending
成功状态(有对应的处理) fulfiled (里面resolve方法调用)
失败状态 (有对应的处理) rejected (里面代码报错 或者 调用reject)
peomise的方法
原型方法
then 执行成功的回调(也可以执行失败)
varpromise=newPromise((resolve,reject)=>{
//成功的函数调用 传递对应的参数
resolve('成功')
})
promise.then((res)=>{
console.log(`第一次then`,res);
return'hello'
}).then((res)=>{
console.log(`第二次then`,res);
return'world'
}).then((res)=>{
console.log(`第三次then`,res);
return'abc'
}).then()//值穿透 当你的then没有处理它会给到下一个处理
.
then((res)=>{
console.log(`第n次then`,res);
})
catch 执行失败
varpromise=newPromise((resolve,reject)=>{
reject('失败')
// throw new Error('失败了')
})
//.catch默认请求下只执行第一个 如果需要走下面的 那么需要你报错
promise.catch((error)=>{
console.log(`第一次`,error);
thrownewError('失败了')
}).catch((error)=>{
console.log(`第二次`,error);
thrownewError('失败了')
}).catch((error)=>{
console.log(`第三次`,error);
thrownewError('失败了')
}).catch()
.
catch((error)=>{
console.log(`第n次`,error);
})
finally执行完成调用的
//promise promise只能满足于一种状态 进入到成功它就成功了 进入失败就失败了
varsuccess=newPromise((resolve,reject)=>{
//成功的函数调用 传递对应的参数
resolve('成功')
reject('失败')
// throw new Error('失败了')
})
//成功的回调 俩个参数 成功的函数 失败的函数
success.then((res)=>{//res会接收resolve传递的参数
console.log(`res`,res);
},(error)=>{//error 接收reject传递的参数
console.log(`error`,error);
})
//失败的回调 参数1个 传递为一个函数 这个函数可以接收rejected传递的参数
success.catch((error)=>{
console.log(`rejected`,error);
})
//完成就能调用的函数 (成功 失败)
success.finally(()=>{
console.log(`完成了`);
})
静态方法
resolve (返回成功状态的promise)
reject (返回失败状态的promise)
all (并行执行所有的promise 如果遇到rejected就返回reject的promise 如果全部成功就返回所有的结果(promiseresult))
allSettled (互不影响执行对应的promise 返回所有的结果(状态一定是成功))
race (返回最快执行完的peomise)
回调地狱
概述:回调函数的无限嵌套导致当前代码失去了对应的维护价值和对应的可读性(shit山)
promise解决回调地狱(链式调用)
在.then里面返回一个新的promise对象 在对应的异步代码执行完后调用resolve
//利用promise来解决回调地狱的问题
newPromise((resolve,reject)=>{
setTimeout(()=>{
console.log(1);
resolve()
});
}).then(()=>{
returnnewPromise((resolve,reject)=>{
setTimeout(()=>{
console.log(2);
resolve()
});
})
}).then(()=>{
returnnewPromise((resolve,reject)=>{
setTimeout(()=>{
console.log(3);
resolve()
});
})
}).then(()=>{
returnnewPromise((resolve,reject)=>{
setTimeout(()=>{
console.log(4);
resolve()
});
})
}).then(()=>{
console.log(5);
})
async 和 await (es7新增)
概述:async 和 await是对应的两个连用的关键词
async是修饰函数的 await是修饰promise的
await只能在async内使用
async修饰的函数返回一个promise对象 await修饰的promise对象会占用当前的线程 直到对应的promise执行完成才会释放(不释放的话 下面的也动不了)
利用async和await来解决回调地狱
functionfn(v,delay) {
returnnewPromise((resolve,reject)=>{
setTimeout(()=>{
console.log(v);
resolve()
},delay);
})
}
asyncfunctionfn1(){
awaitfn(1,1000)
awaitfn(2,2000)
awaitfn(3,100)
awaitfn(4,0)
console.log(5);
}
fn1()
总结
async是修饰函数的 await是修饰promise对象的
async里面使用await 如果这个await修饰的promise没有执行完 对应的async修饰的函数返回promise状态是pending
如果async修饰的函数内什么都没有 那么对应返回的promise状态是成功(默认函数返回值是undefined)
async修饰的函数 返回值是成功 返回的值传递给then方法
async修饰的函数 如果里面报错 那么返回的是失败 传递的值为报的错
await只能在async里面使用 await会使当前的函数陷入等待
代码执行机制
同步代码执行比异步代码快
同步代码的执行是利用对应的js引擎解析的异步代码执行是利用事件轮询机制执行的
事件轮询机制
先找script标签里面的微任务
按照微任务队列执行完对应的微任务
进入下一个宏任务 执行对应的宏任务代码
进行宏任务对应微任务队列 执行对应微任务
再进行到下一个宏任务 执行对应的微任务
直到对应的宏任务队列和微任务队列被清空
宏任务
script 定时器(setInterval setTimeout) 事件...
微任务
promise.then promise.catch nextTick