带你快速了解闭包

1.闭包的理解

1.怎么产生闭包: 当一个嵌套的内部函数引用了外部函数的变量(函数)时。

2.产生的条件:(1)函数嵌套

                         (2)内部函数引用了外部函数的数据和变量;

3.什么是闭包:存在于嵌套函数中,包含了被引用变量(函数)的对象。

4.常见的闭包:(1)将函数作为另一个函数的返回值

   function fn1() {
     var a = 2;
     function fn2() {
       a++;     //存在于嵌套函数中,包含了被引用变量(函数)的对象
       console.log(a);
     }
     return fn2();
   }

                          (2)将函数作为实参传递给另外一个函数调用

   function showDelay(msy,time) {
     setTimeout(function () {
       alert(msy);
     },time)
   }
   showDelay("aaa",2000);

5.闭包的作用:(1)延长局部变量的生命周期(使用函数内部的变量在函数执行完后,任然存活在内存中);

                         (2)让函数外部可以操作(读/写)函数内部的数据;

6.闭包的生命周期:产生:在嵌套内部函数定义完的时候

                               死亡:嵌套的内部函数成为垃圾对象时候;

7.闭包的应用:自定义js模块

            (定义js模块:具有特定功能的js文件,将所有的数据和功能封装在一个函数内部,只向外暴露n个对象或者方法)

(1)

 function doModule() {   //自定义的js模块
     var msg = "ZhangJie";
     function doSometing() {
       console.log(msg.toUpperCase());
       }
     function doOtherthing() {
       console.log(msg.toLowerCase());
     }
     return {   //向外暴露
       doSomething:doSometing,
       doOtherthing:doOtherthing
     }
   }

   var d = new doModule();
   d.doOtherthing();
   d.doSomething();

(2)

(function (w) {
  var msg = "ZhangJie";
  function doSometing() {
    console.log(msg.toUpperCase());
  }
  function doOtherthing() {
    console.log(msg.toLowerCase());
  }
  w.Module ={ //向外暴露
    doSomething:doSometing,
    doOtherthing:doOtherthing
  }
})(window);

引入js文件在使用
   Module.doOtherthing();
   Module.doSomething();

8.缺点:函数执行完,函数内部的局部变量没有释放,占用的时间会变长,容易造成内存泄漏

9.解决方法:能不使用闭包就不使用

                   即使释放 赋值为null

10.常见的面试题

(1)

 var name = "the window";
  var obj = {
    name:"my object",
    getName:function () {
      return function () {
        return this.name; //注意this是谁
      }
    }
  };
  console.log(obj.getName()());  //the window 

(2)


  var name2 ="the window";
  var obj2 = {
    name2:"my obj2",
    getName:function () {
      var that = this;
          return function () {
           return that.name2;
      }
    }
  }
  console.log(obj2.getName()()); // my obj2

(3)

function fun(n,o) {
    console.log(o);
    return {
      fun:function(m){
        return fun(m,n)
      }
    }
  }
  var a = fun(0);  //undefined
 a.fun(1);   //0
 a.fun(2);   //0
 a.fun(3);   //0
 var b = fun(0).fun(1).fun(2).fun(3);  //undefined 0 1 2
 var c = fun(0).fun(1);  //undefined 0 
 c.fun(2);    //1
 c.fun(3);   //1


注意:闭包会存储值

常见需求: 给每一个按钮绑定点击事件,且按钮内获取当前为第几个按钮

 1.错误方法 - 出现闭包现象1

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

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
    </style>
</head>

<body>
    <div id="box1">
        <button>button1</button>
        <button>button2</button>
        <button>button3</button>
        <button>button4</button>
        <button>button5</button>
        <button>button6</button>
        <button>button7</button>
    </div>
    <script>
        //4.1.有多个按钮,给每个按钮绑定点击事件
        var buttons = document.querySelectorAll("button");
        for (var i = 0; i < buttons.length; i++) {    
                buttons[i].onclick = function () {
                   console.log(i);  //点击任意按钮打印数字7
                }
        }
    </script>
</body>

</html>

 解释: 最简单的理解 - for内,点击事件外,为一个作用域,在这个作用内,i可以为0,,1,2,3,4,5,6

                                   - 点击事件内为一个作用域,点击事件内的数据是for循环已经执行完的数据,即式在循环完毕后,i变为7

            比较绕一点的理解   同步异步执行的问题,for循环为同步执行,需要紧挨着步骤执行


2.如何去解决这种闭包 - 达到内部使用外部的i

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

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
    </style>
</head>

<body>
    <div id="box1">
        <button>button1</button>
        <button>button2</button>
        <button>button3</button>
        <button>button4</button>
        <button>button5</button>
        <button>button6</button>
        <button>button7</button>
    </div>
    <script>
        var buttons = document.querySelectorAll("button");
        // 利用立即执行函数
        for (var i = 0; i < buttons.length; i++) {    
            (function (i) {
                buttons[i].onclick = function () {
                    buttons[i].style.display = 'none';
                }
            })(i)
        }
    </script>
</body>

</html>

原理解释 - 利用立即执行函数将值传递到点击事件内

3.利用let进行解决

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

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
    </style>
</head>

<body>
    <div id="box1">
        <button>button1</button>
        <button>button2</button>
        <button>button3</button>
        <button>button4</button>
        <button>button5</button>
        <button>button6</button>
        <button>button7</button>
    </div>
    <script>
        let buttons = document.querySelectorAll("button");
        for (let i = 0; i < buttons.length; i++) {
            buttons[i].onclick = function () {
                buttons[i].style.display = 'none';
            }
        }
    </script>
</body>

</html>

原理解释 - let会将值进行保存 - 推荐使用,方法简单好理解

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值