JavaScript闭包原理与使用

本文深入探讨JavaScript中的闭包概念,解释其作为作用域桥梁的角色,防止变量污染。通过实例展示了闭包如何创建独立的作用域,以及在DOM事件处理和异步操作中的应用。闭包在解决循环中变量共享问题上展现出强大的能力,确保函数内部状态的持久化。
摘要由CSDN通过智能技术生成

闭包

    闭包就是能够读取其他函数内部变量的函数,例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数”。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。
    闭包主要作用目的是防止变量污染,让闭包所在的函数中有相对独立的命名空间和作用域

实例

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-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>
</body>
</html>
<script charset="utf-8">
     /*var a = 1;
     var a_fn = 10,
         a_fn_fn1 = 20;
     function fn(){
         var a_fn = 2;
         console.log("我在fn中"+a);//可以直接访问全局变量a
         function fn1(){
             var a_fn_fn1 = 3;
             console.log("我在fn中的fn1中"+a);
             console.log("a_fn in fn1 "+ a_fn);
             function fn2(){
                 //这里就全部访问到
                 console.log("我在fn中的fn1中的fn2中")
                 console.log(a,a_fn,a_fn_fn1);
             }
             return fn2;
         }
         return fn1;
     }
     fn()()();//作用域链的典型案例,每执行一次括号,就执行了返回的一个函数
      console.log(a_fn);//这里报错,在外面访问不了函数内部的变量
    console.log(a, a_fn, a_fn_fn1);//这里的变量和函数中定义的变量完全没有冲突,就可以实现相对独立的命名空间*/

      /*function fun1(){
          var a = 1;
          function fun2(){
              a++;
              return a;
          }
          return fun2;
      }

      var f = fun1();
      console.log(f());
      f();
      f();
      console.log(f());//结果变为5了,说明每次执行f的时候,都会让a在原来的基础上计算
     var f1 = fun1();//重新使用一块新的内存空间
     console.log(f1());//这里的值又变回2了,说明每次用Var定义变量的时候,都会有一个新的首地址,相当于定义了一个新的函数,和之前定义的完全没有冲突
      var f2 = f;//将f这个首地址给了f2
     //同一个函数,同一片内存空间
      console.log(f2());//这个地方的值是6,说明我们f2和f的首地址指向同一个地方,f2和f相当于是*/

     //------------闭包在dom中的作用
   /*
   //点击按钮任意按钮都是现实我是按钮3的问题
    var nodes = document.getElementsByTagName("button");
    for(var i = 0; i< nodes.length; i++){
        nodes[i].onclick = function(){
            alert("我是按钮"+i);
        }
    }*/

   /*var arr = [];
    for(var i = 0; i < 4; i++){
        setTimeout(() => {
            arr.push(i);
        },1000);
    }*/
    console.log(arr);//这里是空数组,因为我们使用了异步操作,当我们打印arr的时候,arr还没有赋值
     //---------------------
     /* var arr = [];
      for(var i = 0; i < 4; i++){
          setTimeout(() => {
             arr.push(i) //并不是把0-3赋值进去,而是循环结束以后的i值4
          }, 1000);
      }
      setTimeout(() => {
          console.log(arr);//这里的结果都是4
      }, 5000);*/

     //--------------下面的过程才是上边循环过程
    /*  var arr = []
      i = 0;
      setTimeout(() => {
             arr.push(i) //并不是把0-3赋值进去,而是循环结束以后的i值4
          }, 1000);
      i = 1;
      setTimeout(() => {
             arr.push(i) //并不是把0-3赋值进去,而是循环结束以后的i值4
          }, 1000);
      i = 2;
      setTimeout(() => {
             arr.push(i) //并不是把0-3赋值进去,而是循环结束以后的i值4
          }, 1000);
      i = 3;
      setTimeout(() => {
             arr.push(i) //并不是把0-3赋值进去,而是循环结束以后的i值4
          }, 1000);
      i = 4;

      setTimeout(() => {
          console.log(arr);
      }, 5000);*/
     //--------------使用立即执行的函数的方法将i值立刻传过去,闭包原理
      /*var arr = []
      i = 0;
      (function(a){
      setTimeout(() => {
             arr.push(a) //这里的a值是立即传进来的,并不是等1秒以后的i
          }, 1000)
      })(i)
      i = 1;
      (function(a){
      setTimeout(() => {
             arr.push(a) //这里的a值是立即传进来的,并不是等1秒以后的i
          }, 1000)
      })(i)
      i = 2;
      (function(a){
      setTimeout(() => {
             arr.push(a) //这里的a值是立即传进来的,并不是等1秒以后的i
          }, 1000)
      })(i)
      i = 3;
      (function(a){
      setTimeout(() => {
             arr.push(a) //这里的a值是立即传进来的,并不是等1秒以后的i
          }, 1000)
      })(i)
      i = 4;

      setTimeout(() => {
          console.log(arr);
      }, 5000);*/
     //------------------------------再回来修改之前的循环
      /*var arr = [];
      for(var i = 0; i < 4; i++){
          (function(a){
          setTimeout(() => {
             arr.push(a) //这里的a是立即将i传进来的a,只不过是等1秒后执行而已
          }, 1000);
          })(i)
      }
      setTimeout(() => {
          console.log(arr);//这里的结果是[0,1,2,3]
      }, 5000);*/

     //------------再看遗留问题解决方案
     var nodes = document.getElementsByTagName("button");
     for(var i = 0; i < 3; i++){
         (function(a){nodes[a].onclick = function(){
             alert("我是按钮"+a+1);
         }
         })(i)
     }

</script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值