首页 > 其他分享 >day20闭包和promise

day20闭包和promise

时间:2022-10-26 20:45:10浏览次数:47  
标签:闭包 resolve console 函数 day20 promise Promise log

闭包

概述:在函数内返回一个函数(函数嵌套函数),内部函数有外部函数的引用。

函数的生命周期

函数的预编译阶段:

1.开辟一个内存空间

2.将对应的代码放到这个内存空间

函数的执行阶段

1.将函数开辟的空间放在执行栈上

2.然后执行栈开始执行对应函数对应空间的代码块

3.代码如果需要开辟空间,就在对应函数的内存空间上开辟

4.当不需要使用这个函数时,函数的内存空间就会被回收,里面的代码开辟的空间也会被回收

如果需要保持i的状态,就可以将i放到引用数据类型里面,然后保证这个引用数据类型对象的引用,这时gc就不会回收i了,也可以通过返回函数的形式保证i的唯一性

function fn(){
var i = 0
i++
retrun {
i
}
}
var obj = fn()
console.log(obj.i) //1

function fn(){
var i = 0
return function(){
i++
console.log(i)
}
}
var f = fn()
f() //1
f() //2
f() //3

 

这种保证i不被回收的机制就是闭包

闭包优缺点

优点:内部函数可以对外部函数的参数和变量引用,使得参数和变量的作用范围扩大。

          对应的参数不被回收,使用的时候不需要重新开辟空间,速度更快

         作为缓存

缺点: 内部函数要一直保持对外部函数里面参数和变量的引用

           因为不会被回收那么对应的内存空间就会一直占用

闭包的应用

防抖(在规定时间内只执行一次 执行最后一次)

//第一个参数是做的操作 第二个参数是等待时间
function debounce(fn,delay){
var timer = null
return function(){
clearTimeout(timer) //清除上一次的等待
//开始新的等待
timer = setTimeout(fn,delay)
}
}

节流(在规定时间内执行第一次 减少执行次数)

//操作 执行一次的时长
function throttle(fn,delay){
var timer = null
return function(){
//判断上一次是否走完
if(timer) return
//上一次走完了开始下一次
timer = setTimeout(()=>{
fn()
//走完了要将节流阀设置为false
timer = null
},delay)
}
}

防抖和节流的区别
防抖执行最后一次 节流执行第一次
防抖在规定时间内只执行一次 节流是在规定时间内减少对应的执行次数
防抖对应的开始下一次先要清除上一次 节流开始下一次先要判断上一次是否执行完毕

函数柯里化 (将多个参数的函数拆分为多个单参数的函数 可以自由的组合)

function sum(a,b){
return a+b
}
sum(1,2)
简单的函数柯里化
function sum(a){
return function(b){
return function(c){ return a+b+c } } } console.log(`sum(1)(2)(3)`, sum(1)(2)(3));//6 console.log(`sum(1)(2)`, sum(1)(2));//fn

高阶函数柯里化

//传递一个函数 (参数没到返回函数 参数到了返回结果)
function currying(fn) {
//获取currying传递的参数
let args = Array.prototype.slice.call(arguments,1)
return function () {
//将对应的函数的参数和curry传递参数做连接
let arg = Array.from(arguments).concat(args)
//判断参数个数是否一样
if(arg.length < fn.length){
//参数没到返回函数
return currying.call(this,fn,...arg)
}else{
//参数到了 调用方法返回结果
return fn.apply(this,arg)
}
}
}

核心就是参数没有够返回对应的函数 参数够了返回结果

Promise(承诺   es6新增)

概述:有三种状态 等待状态(pending)、成功状态(fulfilled)、失败状态(rejected)

等待状态(没有处理) pending
成功状态 (有对应的处理) fulfilled (里面resolve方法调用)
失败状态 (有对应的处理)rejected (里面代码报错 或者 调用reject)

构建promise对象

//里面传递的参数是一个函数
//这个传递的函数里面有俩个参数 这个俩个参数也是一个函数
//这个函数里面的第一个参数为成功的函数 resolve 第二个参数为失败的函数 reject (这个俩个函数
都是异步的)
var promise = new Promise((resolve,reject)=>{
//包含异步的代码
console.log('hello promise')
})

promise的方法

原型方法

then 执行成功的回调

catch执行失败

finally执行完成调用

var promise = new Promise((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);
})


var promise = new Promise((resolve,reject)=>{
reject('失败')
// throw new Error('失败了')
})
//.catch默认请求下只执行第一个 如果需要走下面的 那么需要你报错
promise.catch((error)=>{
console.log(`第一次`, error);
throw new Error('失败了')
}).catch((error)=>{
console.log(`第二次`, error);
throw new Error('失败了')
}).catch((error)=>{
console.log(`第三次`, error);
throw new Error('失败了')
}).catch()
.
catch((error)=>{
console.log(`第n次`, error);
})



//promise promise只能满足于一种状态 进入到成功它就成功了 进入失败就失败了
var success = new Promise((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 (返回最快执行完成的promise)

/静态方法 Promise.方法名
//resolve方法
//返回一个成功的promise对象
var promise = Promise.resolve('hello')
console.log(`promise`, promise);
promise.then(res=>{
console.log(res);
})
// reject返回一个失败的promise对象
var promise1 = Promise.reject('错误')
console.log(`promise1`, promise1);
promise1.catch(error=>{
console.log(error);
})
//all 传入一个promise数组 并行执行promise数组里面的promise (如果有一个是rejected 那么整
体都是rejected)
var promise2 = Promise.resolve('hello')
var promise3 = Promise.reject('错误')
// var promise3 = Promise.resolve('成功')
var promise4 = Promise.resolve('world')
var promise5 = Promise.resolve('你好')
//all方法返回的是一个promise对象 如果全部成功对应的promiseResult里面的结果就是所有成功 否则
就是错误的结果
var promise6 = Promise.all([promise2,promise3,promise4,promise5])
console.log(promise6);
//传入一个promise数组 返回一个promise对象 不会互相影响 返回所有结果(状态为成功)
var promise7 = Promise.allSettled([promise2,promise3,promise4,promise5])
console.log(promise7);
//竞速 race 传入promise数组 返回最快走完的promise
var promise8 = Promise.race([promise2,promise3,promise4,promise5])
console.log(promise8);

回调地狱

概述:回调函数的而无限嵌套导致当前的代码失去了对应的维护价值及对应的可读性

promise来解决回调地狱(链式调用)在.then里面返回一个新的promise对象 在对应的异步代码执行完后调用resolve

  new Promise((resolve,reject)=>{
             setTimeout(()=>{
                console.log(1);
                resolve()
             })
        }).then(()=>{
            return new Promise((resolve,reject)=>{
                setTimeout(() => {
                    console.log(2)
                    resolve()
                });
            })
        }).then(()=>{
            return new Promise((resolve,reject)=>{
                setTimeout(() => {
                    console.log(3)
                    resolve()
                });
            })
        })

async await(es7新增的)

概述:async和await是对应的连用的两个关键词,async修饰函数,await是修饰promise,await只能在async内使用,async修饰的函数返回一个promise对象,await修饰的promise对象会占用当前的线程 直到对应的promise执行完才会释放

async function fn() {
await new Promise((resolve,reject)=>{ //如果没有放行后面的不会执行
setTimeout(() => {
console.log('hello');
resolve()
})
})
console.log('world');
}
//async修饰完函数执行会返回一个promise对象
console.log(fn());
//async修饰的函数返回的promise对象
//里面的报错 会使当前的promise对象的状态为rejected
//如果里面return内容那么内容将会传递给对应的then
async function fn1(){
throw new Error('错误')
// return '我是fn1'
}
fn1().then(res=>{
console.log(res);
},error=>{
console.log(error);
})
//await会使用当前的函数的线程占用 直到对应的修饰的promise执行完成
// await Promise.reject() 报错

利用async和await来解决回调地狱

 function fn(v,delay){
              return new Promise((resolve,reject)=>{
                setTimeout(()=>{
                    console.log(v);
                    resolve()
                },delay)
              })
        }
        async function fn1(){
              await fn(1,1000)
              await fn(2,2000)
              await fn(3,3000)
              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 ....

标签:闭包,resolve,console,函数,day20,promise,Promise,log
From: https://www.cnblogs.com/zmfhtml5/p/16829951.html

相关文章