闭包的原理以及简单应用场景

    // 所谓的闭包,现在已经基本不使用了
    // 只有一些老项目中,或者是极其特殊的情况中,才会使用

// 什么是闭包

    //   概念:  是js中,函数的一种高级应用方式
    //   作用:  调用函数中局部作用域变量,在函数之外,可以直接使用
    //   正常情况下,只能使用 return 返回 局部作用域变量的数值 
    //   要想调用使用 int 就必须要使用 闭包
    //   return 只能返回一个数值,
    //   使用闭包的形式,可以返回调用,多个数值数据

    // 闭包的执行条件
    //   要使用执行闭包,必须要有3个条件,缺一不可
    //     1, 在函数A中,直接返回一个函数B
    //          函数A的返回值是另一个函数B
    //     2, 函数B中,调用使用函数A中的局部作用域变量
    //     3, 函数A 外部 有一个变量 存储接收 函数B


    // function fun(){
    //     // 定义在函数内部的局部作用域变量
    //     var int1 = 100;
    //     // 通过 return 返回的 int1 中存储的数值100
    //     // 但是这个变量 int 仍然不能被使用
    //     return int1;
    // }

    // fun();

    // 在函数外部,无法直接使用局部作用域变量
    // console.log(int1);


    // 闭包的写法

    // 定义一个函数A
    function funA(){
        // 函数A中有一个局部作用域变量
        var int21 = 100;
        var int22 = 200;
        var int23 = 300;

        // 函数A,返回值,是另一个函数B
        // 函数A的执行结果,返回值就是函数B
        return function funB(){
            // 函数B中,调用执行了函数A中的变量 int3
            var int31 = int21;
            var int32 = int22;
            var int33 = int23;
            console.log(int31,int32,int33);
        }
    }

    // 有一个外部的变量,来存储函数B
    // f 中 存储的是 funA 函数的执行结果,也就是 函数B

    // funA() 的执行结果是 function funB(){}
    // 等于 是 一个匿名函数 const f = function funB(){}
    // f 中 存储的是 funB() 的 内存地址
    // f() 就是 调用的  funB() 这个函数
     const f = funA();
   
   

    // 此时 执行 f() , 就是通过存储的地址, 执行函数B()
     f();

    // 此时,int21变量,在函数外部仍然无法直接使用
    // 但是int21的数值数据,可以在函数外部直接使用
    // console.log(int21);

闭包的简单应用

// 方法1: 最简单最方便的是使用 let 来定义 循环变量
const oLi = document.querySelectorAll(‘li’);

    // var 声明,会只声明一个 循环变量 i
    // 之后做的是 覆盖操作 i 最终只 存储 最终的 i 的数值 5
    // 点击输出的结果都是5
    // for(var i = 0 ; i <= oLi.length-1 ; i++  ){
    //     oLi[i].onclick = function(){
    //         console.log(i);
    //     }
    // }


    // 使用let 声明 循环变量 i 
    // 每次生成一个 独立的 i 存储 独立的数值
    // 每次调用执行的都是 独立的i 中存储的独立的数值
    // for(let i = 1 ; i <= oLi.length ; i++  ){
    //     oLi[i].onclick = function(){
    //         console.log(i);
    //     }
    // }


    // 闭包解决
    // 使用函数,生成独立的 执行空间 , 在执行空间中 存储 独立的循环变量 i
    // 调用时,就有独立的变量,存储独立的数据

    function fun(num){
        // 在函数fun中 有 形参 num 来 存储实参 数值
        // 在函数fun中 定义了 一个新的事件处理函数
        // 在这个事件处理函数中,调用使用了 函数fun 中的 形参num
        // 这个事件处理函数,会绑定给一个标签对象,也就是在函数外部会被调用使用
        // 此时,在函数外部,会调用使用 引用数据类型 也就是 事件处理函数
        // 函数fun 的 执行空间就不会被销毁 
        // 每一个事件处理函数中 num 都是 独立存储,声明在函数fun中的形参
        oLi[num].onclick = function (){
            console.log(num);
        }
    }


    // 通过循环遍历每次调用函数就可以了
    // 这个函数会使用不被销毁的 执行空间 来 存储 形参以及形参中的实参

    for(var i = 0 ; i <= oLi.length-1 ; i++ ){
        // 循环中,i中存储的数值,会被覆盖
        // 但是 通过 fun函数 来以实参的形式,输入 i
        // i 的数值 就会被 fun() 不会销毁的执行空间中 存储
        // 每一次循环,i是不同的数值
        // 数值 存储在 每次循环生成的不同的fun() 函数中
        // 每次fun()函数都会有一个独立的,不被销毁的执行空间,存储 i 的数值
        fun(i);
    }

闭包的特点

    优点同时也是缺点
        1, 函数,执行空间不会被销毁
            优点: 空间中的聂荣,永远存在
            缺点: 会占用大量的内存空间
        
        2, 可以从函数外部调用,使用函数内部的数据
            优点: 调用数据更加方便
            缺点: 容易泄露数据信息,不安全
        3, 保护私有变量
            优点: 私有变量,不会被销毁
            
            缺点: 私有变量存储占用空间
        
    闭包的必要性
        闭包看上去是为了调用函数内的数据
        实际是 为了 防止全局变量污染而采用的一个手段

        如果是声明为全局作用域变量,只要是程序,就可以对这个全局变量进行参数

        为了确保只有指定的特定的程序,可以操作变量,将变量定义为局部作用域变量
        也就是将 变量 声明在函数中

        但是要使用调用变量中存储的数据,理论上不能直接调用使用
        因此,就有闭包这个程序执行方式,来调用函数内部的变量,存储的数值数据
展开阅读全文
©️2020 CSDN 皮肤主题: 1024 设计师: 上身试试 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值