欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

重新理解闭包

程序员文章站 2022-07-01 20:40:08
闭包这个概念 自我几个月前开始学习JS开始 我就一直困惑 之前也有所理解 但是后来长时间不用就给忘记了 闭包:通俗的讲 大多数人所接受的就是 一个函数有权利使用另一个函数里的局部变量 我看到了很多的不同之处 用最简单的代码表示 很符合概念 我觉得闭包就是在体现作用域 inner 函数实在 out 函 ......

闭包这个概念  自我几个月前开始学习JS开始  我就一直困惑

之前也有所理解  但是后来长时间不用就给忘记了

闭包:通俗的讲  大多数人所接受的就是 一个函数有权利使用另一个函数里的局部变量

我看到了很多的不同之处

用最简单的代码表示

function out(){

var age=21;

function inner(){
  
  console.log(age);

}

return inner;

}

var fn=out();
 fn();  //22

很符合概念 

我觉得闭包就是在体现作用域

inner 函数实在 out 函数里面定义地 

所以console(age);

就会变量搜索机制,首先在自己(inner)函数作用域里面找,没找到 就去out函数作用域里面找

找到了  然后输出  如果在out里面没有找到的话  会再往更大的作用域找

一直到window的作用域   下级作用域可以向*问  上级作用域不能向下访问

 

作用域就是指

{  } 

而且JS没有块级作用域

for(var i=0;i<5;i++){

  console.log(i);// 1 2 3 4 5

}

cosole.log(i);//5

i 不会因为出了 for 循环就被销毁了

这点要注意

好了  说了一点作用域方面的知识  现在回到了闭包

闭包核心的就是return 看看代码 就知道了

我的理解就是  return 返回的是inner的函数体   还有 inner所能访问的作用域!

所以 inner 在哪里都可以访问到age 

例子:

function  test(){
               var age=23;
                var fn=out();
                 fn();  //21
             
             }
    
    test();//21

 

 它得到的是 21  而不是22  因为函数体和作用域一起返回了  那么最近的作用域不就是out函数作用域喽

 test 函数里面定义了age也不可能被覆盖滴  因为存在的作用域不同

 它返回了 作用域  所以它访问的都是那个作用域里面的变量 跟你的函数现在所在的作用域无关哦

 闭包其实是一种现象   就是所有人玩DNF都在刷图卖材料赚钱  这种现象叫搬砖

 总结一句话:跟你定义函数作用域有关,跟你执行函数的作用域无关

 与this相反  this 是与定义时无关,与执行时有关  比较记忆

 所以你如果不能很好的理解闭包

 那你就可以像我这样理解 就好了 

 返回的是函数本身+和函数所能访问的作用域

举一个  大家常用的  

闭包Tab栏切换

<!doctype html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <meta name="Generator" content="EditPlus®">
  <meta name="Author" content="">
  <meta name="Keywords" content="">
  <meta name="Description" content="">
  <title>Document</title>
  <style type="text/css">
  *{margin:0;padding:0;}
   .box{
     width:140px;
     height:18px;
     position:relative;
     padding:6px 20px;
     margin:50px auto;
     background:#ff6666;
   }

   .box ul{
     list-style:none;
   } 

   .box li{
      width:18px;
      height:18px;
      background:#ff3300;
      line-height:18px;
      text-align:center;
      float:left;
      margin-right:5px;
      cursor:pointer;
   }

   .current{
     background:#ffccff!important;
   }
  </style>
 </head>
 <body>

  
  <div class="box">
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
        <li>6</li>
    </ul>
  </div>
 
<script type="text/javascript">
     function $(name){
          return document.querySelectorAll(name);
       }

        var  list=$(".box ul li");
        var len=list.length;
       for(var i=0;i<len;i++){
           list[i].onmouseover=(function(n){
               
               return function(){
                  for(var j=0;j<len;j++){
                
                      list[j].className="";
                
                  }
                list[n].className="current";
               
               }
           })(i);


       }



</script> </body> </html>

for循环 每当执行list[i].onmouseover的时候   函数都会立即执行  传入当前的变量i 

返回一个函数  这个就是形成了闭包呗  返回函数和函数能够访问到的作用域

每当触发onmouseover的时候  都会执行 返回的那个函数

然后执行代函数里面的for循环 把所有li的className 清空

在执行list[n]  这句是最重要的  这里的n 就是定义onmouseover的时候传入的i 

因为当定义的时候 函数立即执行 把 i 传递给了匿名函数 这个 i 就在 匿名函数的作用域里面了

每个onmouseover都是保存着各自的 i

所以当触发onmouseover的时候能够让li访问到之前保存在作用域中的 i

也就实现了 点谁 谁背景颜色变化的需求

我是这么理解的  我也是个菜鸟

Over