js闭包的理解及应用场景

函数的声明与执行

  • 函数定义阶段
    1.会在堆内存中开辟一个存储空间 把函数体放在这个空间里 函数中的所有变量不解析
    2.把这个空间地址赋值给函数名 然后储存在栈内存中

  • 函数调用阶段
    1.根据函数名找到对应的函数存储空间
    2.然后再堆内存中再开辟一个函数执行空间
    3.在这个执行空间里面进行函数赋值 和与解析
    4.这时函数储存空间的代码会复制到函数执行空间内 然后执行
    5.执行完毕之后 执行空间销毁
    函数每次执行都会开辟一个执行空间 执行完毕后 执行空间销毁 这个过程也就是所说的垃圾回收机制

  • 函数执行的特殊情况
    当函数返回的是一个复杂数据类型时 并且在函数的外部有变量接收这个复杂数据类型
    只有这个外部变量不在引用函数内部返回值的时候 这个函数执行空间才会销毁
    那么闭包就是利用函数的这个特性来实现的 接下来聊一聊js的闭包

闭包

  • 理解闭包的含义
    闭包形成的三要素:
    1.在函数A内部直接或者间接返回一个函数B
    2.B函数内有A函数的私有变量
    3.A函数的外部有一个变量接收这返回的B函数

  • 闭包空间

当A函数执行完毕后 销毁并且在A函数的内部有一个B函数的存储空间 这个空间就叫做闭包空间

  • 形成闭包的代码结构
function fn(){
     var  num = 1;
     return function b(){
         console.log(num)
      }
}
var f = fn();
f()//1

  • 闭包的作用
    1.可以做缓存
function version() {
    var food = '';
    var obj = {
        eat : function(){
            console.log('我正在吃'+food);
            food = "";
        },
        abb : function (myFood){
            food = myFood;
        }
    }
    return obj;
}
var eater = version();
eater.abb('apple');
eater.eat();//我正在吃apple

2.实现公有变量
函数累加器

function add(){
    varcount = 0;
    function demo(){
        count++;
        console.log(count);
    }
    return demo;
}
var counter = add();
//每次调用一次就会在原有基础上加一;
counter();
counter();
counter();

3.模块化开发防止污染全局变量

function test(){
    var arr = [];
    for(var i = 0;i<10;i++){
        (function(j){
            arr[j]=function(){
                console.log(j+",");
            }
        })(i)
    }
    return arr;
}
var myArr = test();
for (var j = 0 ; j < 10 ; j++){
    myArr[j]();
}
//打印0,1,2,3,4,5,6,7,8,9
  • 闭包的缺点
    当内部函数被保存到外部时就会生成闭包 闭包会导致原有作用域链不释放 造成能存泄露

闭包的应用场景

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title></title>
    <link rel="stylesheet" href="">
</head>

<body>

    <p>hello world</p>
    <button>12</button>
    <button>14</button>
    <button>16</button>

    <script>
        document.querySelectorAll('button')[0].onclick = changeSize(12);
        document.querySelectorAll('button')[1].onclick = changeSize(14);
        document.querySelectorAll('button')[2].onclick = changeSize(16);
        function changeSize(size) {
            return function () {
                document.body.style.fontSize = size + 'px';
            };
        }

    //我们定义行为,然后把它关联到某个用户事件上(点击或者按键)。我们的代码通常会作为一个回调(事件触发时调用的函数)绑定到事件上
    </script>
</body>

</html>

循环绑定事件

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>

    <button>1</button>
    <button>2</button>
    <button>3</button>
    <button>4</button>

    <script>
        var btns = document.querySelectorAll('button')

        for (var i = 0; i < btns.length; i++) {
            (function loop(num) {
                btns[num].onclick = function () {
                    console.log(num)
                }
            })(i)
        }

    </script>
</body>

</html>

发布了8 篇原创文章 · 获赞 1 · 访问量 156

猜你喜欢

转载自blog.csdn.net/weixin_44862325/article/details/104444849
今日推荐