闭包和Promise
文章目录
闭包
概述
函数嵌套函数,内部函数拥有外部函数的引用
优点:
- 避免的了全局污染
- 扩大了对应的变量的作用域
- 使用过程中效率会更高
缺点
- 因为会一直保持引用,会导致内存一直被占用
- 在ie浏览器的情况下会导致内存泄漏
函数的预编译
局部作用域的函数预编译
- 创建AO对象(Activation Object)(开辟一个内存空间)
- 给函数里面的形参、遍历进行赋值操作(undefined)
- 形参和实参同步
- 给对应的函数进行赋值
function foo(a){
console.log(a);
a=10;
console.log(a);
function a(){}
}
foo(1)
//第一步,创建AO对象
AO{
}
//第二步,将形参a的值设置为undefined
AO{
a:undefined
}
//第三步,将实参1赋值给a
AO{
a:1
}
//第四步,函数声明提升
AO{
a:function a(){}
}S
全局作用域的函数预编译
- 创建AO对象(global Object)(开辟一个内存空间)
- 给函数里面的形参、遍历进行赋值操作(undefined)
- 形参和实参同步
- 给对应的函数进行赋值
防抖(debounce)
规定时间内重复触发只执行一次(最后一次)
function debounce(callback ,delay){
let timer = null
return function(){
clearTimeout(timer)
timer = setTimeout(() => {
callback()
clearTimeout(timer)
}, delay);
}
}
let btn = document.querySelector('button')
btn.addEventListener('click',debounce(()=>{
console.log('点击了');
},500))
节流(throttling)
规定一定时间段执行一次
function throttling(callback ,delay){
let timer = null//节流阀
return function(){
// 判断是否有操作进行,如果没有,就执行
if(!timer){
timer = setTimeout(() => {
callback()//执行操作
clearTimeout(timer)
timer = null//释放节流阀
}, delay);
}
}
}
let btn = document.querySelector('button')
btn.onclick=throttling(()=>{
console.log('点击了');
},1000)
函数柯里化(currying)
将一个多参数的函数 分成多个函数 (彼此之间可以任意组成)
//简单柯里化
function sum(a, b, c) {
return a + b + c
}
//简单函数柯里化
function sum(a) {
return function (b) {
return function (c) {
return a + b + c
}
}
}
console.log(sum(1)(2)(3))//6
// 高阶函数柯里化
// 求和
function sum(a, b, c) {
return a + b + c
}
function currying(fn){
//接收传入的参数 arguments (不包含第一个fn)
let args = Array.prototype.slice.call(arguments,1)
return function(){
//接收
let allArgs = args.concat([...arguments])
if(allArgs.length < fn.length){
return currying.apply(this,[fn].concat(allArgs))
}else{
return fn.apply(this,allArgs)
}
}
}
let cuyfn = currying(sum)
console.log(cuyfn(1,2,3));
console.log(cuyfn(1)(2,3));
console.log(cuyfn(1)(2)(3));
核心思路
参数没到返回函数,参数到了返回结果
Promise
概述
Promise 是异步编程的一种解决方案,其实是一个构造函数,自己身上有all、reject、resolve这几个方法,原型上有then、catch等方法。
为什么需要这个?
解决异步问题
将异步代码同步执行
解决回调地狱
特点
-
对象的状态不受外界影响。
Promise
对象代表一个异步操作,有三种状态:
-
pending(进行中)
-
fulfilled(resolved)(已成功)
-
rejected(已失败)
只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是
Promise
这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。 -
-
一旦状态改变,就不会再变,任何时候都可以得到这个结果。
Promise
对象的状态改变,只有两种可能:从pending
变为fulfilled
和从pending
变为rejected
。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise
对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
promise的声明
//传入函数来进行构建 传入的函数内有两个参数传递
//new Promise是一个同步执行的代码 它的里面可以包含异步代码
new Promise((resolved,rejected)=>{
console.log('hello')//同步代码
})
promise相关原型方法
then()
- then用于处理对应的promise状态变化的方法
- 有两个参数,一个是成功的处理函数,一个是拒绝的处理函数
- 成功的处理函数里面可以接受对应的resolve函数携带的参数
- 拒绝的处理函数里面可以接受对应的reject函数携带的参数
- 拒绝的处理函数里面还可以捕获对应的promise中抛出的错误
- 在then中return的数据会被下一级的then方法接收
- then会发生值穿透(上层的then方法没有对应的函数作为参数时)
catch()
- 捕获promise错误,以及reject方法调用的结果(跟then方法中的第二个参数相同)
finally()
- 状态发生变化就会调用的函数(不管成功还是失败)
Promise相关静态方法
所有的静态方法返回的都是一个新的promise对象
resolve()
返回一个状态为成功的promise
reject()
返回一个状态为拒绝的promise
race()
竞速方法,比较执行速度,谁先执行完,不区分状态,返回速度最快的promise
all()
同步并行执行多个promise,返回一个promise,包含所有结果(若遇到reject,则只有一个reject结果)
allSettled()
同步并行执行多个promise,返回一个promise,(只要执行完成,则是resolve)
async及awiat
async和awiat是es7新增的修饰关键词
async属于语法糖(await一定要在async里面使用 且awiat修饰的是promise)
async
- 用于修饰函数,被其修饰的函数会返回一个promise对象
- 在修饰的函数内返回值相当于调用了resolve方法, 返回值会被传递给then
- 在修饰的函数内报错相当于调用了reject方法,错误会被传递给catch
async function sayHello() {
return 'hello'
}
let promise = sayHello()
promise.then((result)=>{
console.log(result)//hello
})
awiat
- 用于修饰promise,且只能是在async修饰的函数内使用,它会让当前的js引擎线程(执行上下文等待),当前修饰的promise状态不为pending的时候就会释放
async function say() {
await new Promise((resolved, rejected) => {
setTimeout(() => {
console.log(1)
resolved()
}, 2000)
})
console.log(2)
}
say()//1 2
使用async和awiat来解决回调地狱
async function test() {
await new Promise((resolved, rejected) => {
setTimeout(() => {
console.log(1)
resolved()
}, 2000)
})
await new Promise((resolved, rejected) => {
setTimeout(() => {
console.log(2)
resolved()
}, 2000)
})
await new Promise((resolved, rejected) => {
setTimeout(() => {
console.log(3)
resolved()
}, 2000)
})
console.log(4)
}
say()//1 2 3 4