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

js 闭包和promise

时间:2022-11-09 19:44:26浏览次数:47  
标签:闭包 resolve console log js promise fn 函数

闭包

概述:

闭包就是在函数内部返回一个函数,内部函数可以对外部函数的属性和方法进行引用,外部的属性和方法不会被js垃圾回收机制所回收 这个结构就称为闭包

函数的生命周期

function fn(){
      var i=0
      i++
      return i
    }
    console.log(fn());//1 第一个i变量
    console.log(fn());//1 第二个i变量
    console.log(fn());//1 第三个i变量

函数在预编译阶段做的事情

  • 开辟一个内存空间
  • 将对应的代码块放到这个内存空间

函数的执行阶段

  • 将对应的函数开辟的这个空间放在执行栈上

  • 执行栈就开始执行对应的函数对应的空间的代码块

  • 这个代码如果需要开辟空间 它就在这个对应的这个函数的内存空间上开辟

  • 当你不需要使用这个函数了 对应的函数的内存空间就会被回收 那么里面的代码开辟的空间也就被回收了

如果我们需要保持i的状态 那么我们可以将这个i放到这个引用数据类型里面 然后保证这个引用数据类型对象的引用,这个时候gc就不会回收对应的这个i了

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

通过上述代码 我们可以保持对应i的引用,保证i不会被回收,以返回一个引用数据类型来保持对应i的引用。 那么对应的函数也是一个引用数据类型,那么我们是不是也可以通过返回函数的形式来做到保证i的唯一性。

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

闭包的优劣

优势
  • 内部函数拥有外部函数参数和变量的引用,使用我们的参数和变量的作用范围被扩大。

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

  • 作为缓存

劣势
  • 内部函数要一直保持对外部函数里面参数和变量的引用。

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

闭包的应用

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

示例 (等电梯)

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 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)
        }
    }
}

调用

function sum(a,b,c){
    return a+b+c
}
console.log(`sum(1,2,3)`, sum(1,2,3));
let fn = currying(sum)
console.log(`fn(2)`, fn(2));//函数
console.log(`fn(2)(3)`, fn(2)(3));//函数
console.log(`fn(2)(3)(1)`, fn(2)(3)(1));//6
console.log(` fn()()()(2)()()(3)()()()(1)`, fn()()()(2)()()(3)()()()(10));//15

Promise

概述:promise是es6新增的一个类,这个类翻译为承诺,它有三种状态 等待状态,成功状态,拒绝状态。它被设计为异步的,它里面的内容是异步的(方法为异步的)

promise的三种状态

  • 等待状态(没有处理) pending

  • 成功状态 (有对应的处理) fulfilled (里面resolve方法调用)

  • 失败状态 (有对应的处理)rejected (里面代码报错 或者 调用reject)

构建promise对象

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

promise的方法

then 执行成功的回调

catch 执行失败的回调

finally 执行完成调用的

静态方法
  • 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

//利用promise来解决回调地狱的问题
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()
        });
    })
}).then(()=>{
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log(4);
            resolve()
        });
    })
}).then(()=>{
    console.log(5);
})

代码执行机制

同步代码执行比异步代码快

同步代码的执行是利用对应的js引擎解析的

异步代码执行是利用事件轮询机制执行的

事件轮询机制
  • 先找script标签里面的微任务

  • 按照微任务队列执行完对应的微任务

  • 进入下一个宏任务 执行对应的宏任务代码

  • 进行宏任务对应微任务队列 执行对应微任务

  • 再进行到下一个宏任务 执行对应的微任务

  • 直到对应的宏任务队列和微任务队列被清空

宏任务

script 定时器(setInterval setTimeout) 事件...

微任务

promise.then promise.catch nextTick ....

标签:闭包,resolve,console,log,js,promise,fn,函数
From: https://www.cnblogs.com/tch001/p/16874921.html

相关文章

  • Promise与async、await结合使用
    Promise与async、await结合使用functionfun(){returnnewPromise((resolve,reject)=>{//返回一个Promise对象setTimeout(()=>{//此处也可以使用调其......
  • EXTJS 中Grid控件的常用代码
    1、定义列varcm=newExtgridColumnModel([{header:编号,dataIndex:id},{header:名称,dataIndex:name},{header:描述,dataIndex:descn}......
  • 2022-11-09 js 秒数转换成时分
    注:本文转载于http://t.csdn.cn/AHK3yfunctionformatSeconds(value){varsecondTime=parseInt(value);//秒varminuteTime=0;//分......
  • git warning: LF will be replaced by CRLF in package.json解决办法
    敲完代码后,如果修改了package.json文件,在终端用git进行同步时,gitadd.后会报如下错误:warning:LFwillbereplacedbyCRLFinpackage.json.Thefilewillhaveits......
  • java 串口工具jSerialComm
    由于项目之前用的串口工具RXTX只支持到jdk1.8然后项目目前用到的jdk是13的所以在网上找了一下找到了这个 jSerialComm目前使用是支持13及1.8的没做其它jdk版本测试......
  • [Kyana]优雅配置nodejs环境
    00|前排提示Node真是好,理包两行泪。01|本体安装从官网下载安装包,或使用其它下载非最新版,非Windows系统参考官方指南安装。Windows版自带npm包管理器,安装时需要注意修改......
  • nodejs pm2 详解
    一、PM2是什么pm2是可以用于生产环境的Nodejs的进程管理工具,并且它内置一个负载均衡。它不仅可以保证服务不会中断一直在线,并且提供0秒reload功能,还有其他一系列进程管理......
  • javascript基础知识之闭包和递归
    一,什么是闭包,会出现什么问题?如何避免?1、函数里面包含的子函数,子函数访问父函数的局部变量2、通过return将子函数暴露在全局作用域,子函数就形成闭包3、通过闭包,父函数的局......
  • js设计模式-类式继承
    js中怎么实现类式继承呢?首先声明父类,在声明子类,然后将父类的实例赋予给子类的原型就可以了。假设父类长这样:varBook=function(id,name,price){//私有的属性......
  • 小程序promise封装
    小程序promise封装//ajaxpromise封装constrequestFetch=(url,method,param)=>{//一个页面中可能会发送多个请求,ajaxTimes记载同时发送异步请求代码的次数,目......