最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • js闭包之——相信我,这次真是手把手教

    正文概述 掘金(白毛欧尼酱)   2021-07-06   673

    一、理解与记忆核心

    二、闭包的理解与实现

    首先

    根据【闭包是一个访问了其他函数内部作用域的函数】的定义

    在不知道闭包的情况下,当我们想要在函数外使用函数内部的变量时,我们通常会想到什么?

    1.全局变量!!

    将函数内的局部变量变成全局变量, 在全局作用域中声明,在函数中赋值,这样,只要调用过该函数,就可以在函数外部取到想要的值

    //全局变量
    var a;//变量声明,let和const声明的变量充其量只能算script块下的,没有挂到window全局,因此,这里我还是改成var
    function fn(){
        a=20;//变量赋值
    }
    fn();//函数调用
    console.log(window.a);//取到函数内作用的结果
    

    为了图片展示方便,以下图片中我还是使用node环境运行,但运行结果保证与浏览器中一致 js闭包之——相信我,这次真是手把手教 还有一个更好玩的 js闭包之——相信我,这次真是手把手教 每次调用都相当于对同一个全局变量进行了+1的操作,可以实现累积的效果

    但是!! 很多时候,我们并不想声明一个全局变量,因为每次访问a都相当于访问window.a,这样看起来是不是感觉太占用window变量的资源了, 如果只想用局部变量但又想在函数外访问呢?

    2.不想使用全局变量

    如果直接在外部使用局部变量,结果就报错了!a is not defined

    // 局部变量
    function fn(){
        let a=30;
    }
    fn();
    console.log(a);
    

    那应该怎么办呢? 两种思路,

    2.1.直接将局部变量返回

    将a返回,把a从函数里抛出,让外面的aa来接住它!

    function fn(){
        let a = 40;
        return a;
    }
    let aa = fn();
    console.log(aa);
    

    除此之外,我还可以对a进行一番play之后再返回

    js闭包之——相信我,这次真是手把手教

    2.2.暴露一个访问器,让外部间接访问

            function fn(){
                let a=40;
                // 注意,get和set不要加let或var,这样才相当于挂载到了全局对象上,否则外部是无法访问get和set的
                //这里的get相当于一个全局变量,被挂载到了全局对象上
                get = function(){
                    return a;
                };
            }
            fn();
            let aa = get();
            console.log(aa);
            console.log(window.get());
    

    js闭包之——相信我,这次真是手把手教

    js闭包之——相信我,这次真是手把手教

    同样,可以对a进行一番play之后再返回

    js闭包之——相信我,这次真是手把手教 但是,如果我想多次对a进行该操作呢?

    3.对该局部变量进行多次累计操作

    同样对两种方法进行测试

    3.1.直接返回

    js闭包之——相信我,这次真是手把手教 从图中结果可以看出,由于每次函数执行完毕时,js会进行垃圾回收,将作用域清空回收,每次a都被重新赋值,因此不管我调用多少次,都只会返回一次调用的结果 如何解决呢? 通过1中全局变量的例子可以得到一些启发 js闭包之——相信我,这次真是手把手教 如果我们在(父)函数中有一个局部变量,并且(父)函数中有另一个(子)函数来访问该局部变量,那我们每调用一次(子)函数,由于(子)函数内有对其外部的a变量的引用,就可以实现该局部变量a的累积变动,为了能在(父)函数外部能操作,将操作的(子)函数直接返回

    js闭包之——相信我,这次真是手把手教 而这,就是我们的主角闭包了,因此才说一般闭包表现为一个函数中返回另一个函数

    3.2.暴露一个访问器,让外部间接访问

    js闭包之——相信我,这次真是手把手教 为什么这样就可以呢?其实这种方式也属于闭包的一种,因为这里的get和set也满足了闭包【访问了其他函数内部作用域】的定义 所以,也不一定是return一个函数才能产生闭包,只是大部分情况是这样

    三、闭包的应用场景

    1、例如定时器、事件监听以及Ajax请求等这类使用回调函数的,基本都利用到了闭包,使用定时器的例子,如防抖/节流:

    // 防抖
    const debounce = (fn,delayTime) => {
      let timerId, result
      return function(...args) {
        timerId && clearTimeout(timerId)
        timerId = setTimeout(()=>result=fn.apply(this,args),delayTime)
        return result
      }
    }
    
    // 节流
    const throttle = (fn, delayTime) => {
      let timerId
      return function(...args) {
        if(!timerId) {
          timerId = setTimeout(()=>{
            timerId = null
            return result = fn.apply(this,args)
          },delayTime)
        }
      }
    }
    

    2、IIFE(立即执行函数),这种函数比较特别,它拥有独立的作用域,不会污染全局环境,但是同时又可以防止外界访问内部的变量,所以很多时候会用来做模块化或者模拟私有方法 举个例子:

    var global = '全局变量'
    let Anonymous = (function() {
      var local = '内部变量'
      console.log(global)    // 全局变量
    })()
    console.log(Anonymous.local)   // local is not defined
    
    =======分割线==============
    
    var global = '全局变量'
    let Anonymous = (function() {
      var local = '内部变量'
      console.log(global)    // 全局变量
      return {
        afterLocal: local
      }
    })()
    console.log(Anonymous.afterLocal)   // 内部变量
    

    3.计时器

    function counter2(){
        let time = 0;
        return function(){
            time++;
            console.log(time);
            if(time>10){
                clearInterval(timer);
            }
        }
    }
    let count = counter2();
    count();
    count();
    count();
    

    4.如何在浏览器中查看闭包

            function fn1(){
                let a=11;
                let b="bbb";
                return function fn2(){
                    let c="c";
                    console.log(c);
                    console.log(a);
                }
            }
            fn1()();
    

    js闭包之——相信我,这次真是手把手教 当运行到fn2内部时,就产生了闭包Closure,且里面只有引用到的外部函数变量a

    四、总结一下

    一、什么是闭包?

    访问了其他函数内部作用域的函数

    二、产生闭包的原因?

    当前函数内保持对上层作用域的引用

    三、闭包的优缺点?

    优点:

    • 可以让一个变量长期存储在内存中。
    • 避免全局变量的污染。

    缺点:

    • 常驻内存,增加内存使用量。
    • 使用不当会很容易造成内存泄露。

    五、参考

    juejin.cn/post/696642…

    zhuanlan.zhihu.com/p/22486908

    六、往期精彩

    原型与原型链

    this指向


    起源地下载网 » js闭包之——相信我,这次真是手把手教

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元