zoukankan      html  css  js  c++  java
  • js闭包

    需求:点击某个按钮,提示点击的是第n个按钮

        var btns=document.getElementsByTagName('button');
        for(var i=0;i<btns.length;i++){
            var btn=btns[i];
            btn.onclick=function () {
                alert('点击'+(i+1)+'个');
            }
        }
    

      运行上面的代码,i始终是btns.length+1

    改进:

       var btns=document.getElementsByTagName('button');
        for(var i=0;i<btns.length;i++){
            (function (i) {
                var btn=btns[i];
                btn.onclick=function () {
                    alert('点击'+(i+1)+'个');
                }
            })(i);
        }
    

      如何产生闭包:

    当一个嵌套的内部(子)函数引用了嵌套的外部(父)函数的变量(函数)时,就产生了闭包.

    使用chrome调试查看

     理解一:闭包是嵌套的内部函数

    理解二:包含被引用变量(函数)的对象

    注意:闭包存在于嵌套的内部函数中

    常见的闭包使用形式:

    1.将函数作为另一个函数的返回值

      

    function  fn1() {
        var num=10;
        function fn2(){
            num++;
            console.log(num);
        }
        return fn2;
    }
    var f=fn1();
    f();//11
    f();//12

      

    2.将函数的形参作为实参传递给另一个函数调用.

    //大的函数中包含小的函数,小函数中引入了大函数的变量,就形成了闭包
    function logMsgDelay(msg,time) {
        setTimeout(function () {
            console.log(msg);
        },time);
    }
    logMsgDelay('老石',1000);
    

      

     

    function myTool(){
        var money=1000;
        //提供操作私有函数的操作
        function get(){
            money*=10;
            console.log('总资产:'+money+'元');
        }
        function send(){
            money--;
            console.log('花了一笔钱,总资产:'+money+'元');
        }
        return {
            'get':get,
            'send':send
        };
    }
    

      调用:

    <script type="text/javascript" src="s/myTool.js"></script>
    <script>
       var toolObj= myTool();
       toolObj.get();
    
    </script>
    

      另一种写法:

    (function(w){
       var money=1000;
       function get(){
            money*=10;
            console.log('总资产:'+money+'元');
        };
       function send(){
            money--;
            console.log('花了一笔钱,总资产:'+money+'元');
       }
       w.myTool={
           'get':get,
           'send':send
       }
    })(window)
    

      

     myTool.get();
       myTool.send();
    

      高级排他:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            li{
                border:1px solid #000;
                background-color: #ccc;
                cursor: pointer;
            }
            .current{
                background-color: orangered;;
            }
        </style>
    </head>
    <body>
    <ul>
        <li class="current"></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
    </ul>
    <script>
    
        window.onload = function () {
           var allLis = document.getElementsByTagName('li');
           for(var i=0; i<allLis.length; i++){
               var li = allLis[i];
               li.onmouseover = function () {
                   for(var j=0; j<allLis.length; j++){
                        allLis[j].className = '';
                   }
                   this.className = 'current';
               }
           }
       }
    
    window.onload = function () {
        var allLis = document.getElementsByTagName('li');
        // 记录移动前选中li对应的索引
        var preSelectLiIndex = 0;
        for(var i=0; i<allLis.length; i++){
            (function (i) {
                var li = allLis[i];
                li.onmouseover = function () {
                    // 清除
                    allLis[preSelectLiIndex].className = '';
                    // 设置
                    this.className = 'current';
                    // 赋值
                    preSelectLiIndex = i;
                }
            })(i);
        }
    }
    </script>
    </body>
    

      实现函数节流:

    var timer = null;
          window.onresize = function () {
              clearTimeout(timer);
              timer = setTimeout(function () {
                  console.log('输出的内容!!!!');
              }, 200);
          }
    

      内存泄露:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>02_内存溢出与内存泄露</title>
    </head>
    <body>
    
    <!--
    1. 内存溢出
       一种程序运行出现的错误
       当程序运行需要的内存超过了剩余的内存时, 就抛出内存溢出的错误
    
    
    2. 内存泄露
       占用的内存没有及时释放
       内存泄露积累多了就容易导致内存溢出
       常见的内存泄露:
        1. 占用内存很大的全局变量
        2. 没有及时清理的计时器/定时器
        3. 闭包
    -->
    
    <script type="text/javascript">
        // 1. 内存溢出
       /* var arrObj = {};
        for(var i=0; i<100000000; i++){
            arrObj[i] = new Array(999999);
            console.log(arrObj);
        }*/
    
    
       // 2. 常见的内存泄露
        // 占用内存很大的全局变量
       /* var num = new Array(99999999);
        var num1 = new Array(99999999);
        var num2 = new Array(99999999);
        var num3 = new Array(99999999);
        var num4 = new Array(99999999);
        var num5 = new Array(99999999);
        var num6 = new Array(99999999);
        var num7 = new Array(99999999);
        num = null;*/
    
    
       // 没有及时清理的计时器/定时器
       /* var intervalId = setInterval(function () {
            console.log("-----");
        }, 1000);
        clearInterval(intervalId);*/
    
       // 闭包
        function fn1() {
            var num  = 1111;
            function fn2() {
                num--;
                console.log(num);
            }
    
            return fn2;
        }
    
        var f = fn1();
        f();
    
        f = null;
    </script>
    </body>
    </html>
    

      构造函数设置属性和方法

    <script type="text/html">
    
        // 注意: 以下的属性和方法, 都是绑定在使用构造函数创建出来的对象p上; 最终使用的时候也是使用对象p来进行访问;
        // 我们把这种类型的属性和方法, 称为 实例属性/实例方法
        function Person(name, age, doFunc) {
            this.name = name;
            this.age = age;
            this.doFunc = doFunc;
        }
    
        var p1 = new Person('sz', 18, function () {
            console.log('sz在上课');
        });
        var p2 = new Person('王二小', 18, function () {
            console.log('王二小在放羊');
        });
    
        console.log(p1.name);
        console.log(p1.age);
        p1.doFunc();
    
        console.log(p2.name);
        console.log(p2.age);
        p2.doFunc();
    </script>
    

      

    // 静态属性, 静态方法
    // 绑定在函数身上, 一定要注意: 函数本质也是一个对象, 既然是个对象, 那么就可以动态的添加属性和方法
    // 只要函数存在, 那么绑定在它身上的属性和方法, 也会一直存在
    // 想要记录总共创建了多少个人?

    function Person(name, age, doFunc) {
            this.name = name;
            this.age = age;
            this.doFunc = doFunc;
            if (!Person.personCount) {
                Person.personCount = 0;
            }
            Person.personCount++;
        }
    
        Person.printPersonCount = function () {
            console.log('总共创建了'+ Person.personCount + '个人');
        };
    
    
        var p1 = new Person('sz', 18, function () {
            console.log('sz在上课');
        });
        var p2 = new Person('王二小', 18, function () {
            console.log('王二小在放羊');
        });
    
        console.log(p1.name);
        console.log(p1.age);
        p1.doFunc();
        console.log(p2.name);
        console.log(p2.age);
        p2.doFunc();
    
        Person.printPersonCount();
    

      

  • 相关阅读:
    maven报错【Could not calculate build plan: Plugin org.apache.maven.plugins:maven-resources-plugin:2.6 or one of】
    Srping框架中使用@query注解实现复杂查询
    FreeMarker自定义TemplateDirectiveModel
    SpringMVC和Freemarker整合,带自定义标签的使用方法
    关于FreeMarker自定义TemplateDirectiveModel
    滑块验证码【插件待研究】
    注册页面 注册码【欠缺较多 待完善】
    IO流-文件的写入和读取
    Date、String、Calendar相互转化
    Runtime类
  • 原文地址:https://www.cnblogs.com/sunliyuan/p/12615763.html
Copyright © 2011-2022 走看看