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

    闭包的理解:

      简单来说,闭包就是在另一个作用域中保存了一份它从上一级函数或作用域取得的变量(键值对),而这些变量(键值对)是不会随着上一级函数的执行完成而被销毁。

      常用的闭包实现方法:

        1.函数闭包   

    (function(){
        //函数闭包
    })()

        2. try catch

    try{
    
    }catch(e){
         //catch闭包
    }

        3.with 对象闭包

    with(obj){
          //对象闭包
    }

    闭包的常用三种实现方法:

      找一个经典例子来演示闭包的实现方法。

    <!doctype html>
    <title>javascript闭包</title>
    <meta charset="utf-8"/>
    <script type="text/javascript">
      window.onload = function(){
        var lists = document.getElementsByTagName('li');
         for(var i = 0,len = lists.length; i < len; i++){
            lists[i].onclick = function(){
                alert('点击的是:' + i);
            }
         }
      }
    </script>
    <ul>
      <li id="list1">测试列表</li>
      <li id="list2">测试列表</li>
      <li id="list3">测试列表</li>
      <li id="list4">测试列表</li>
      <li id="list5">测试列表</li>
    </ul>

    本来是想点依次点击li弹出0 1 2 3 4,可是弹出的却是4 4 4 4 4。

      注:onclick绑定的函数function(){alert('点击的是:'+i)}的作用域为对应的li对象,而函数里面的i的作用域为window,每次循环window.i的值都被重新赋值,因此,循环完后,i已经是4。所以点击哪个都是4。

     解决方法:

      1. 使用函数闭包

    <!doctype html>
    <title>javascript闭包</title>
    <meta charset="utf-8"/>
    <script type="text/javascript">
      window.onload = function(){
        var lists = document.getElementsByTagName('li');
         for(var i = 0,len = lists.length; i < len; i++){
            lists[i].onclick = (function(){
                var num = i;
                return function(){
                    alert('点击的是:' + num);
                }
            })()
         }
      }
    </script>
    <ul>
      <li id="list1">测试列表</li>
      <li id="list2">测试列表</li>
      <li id="list3">测试列表</li>
      <li id="list4">测试列表</li>
      <li id="list5">测试列表</li>
    </ul>

     或者

    <!doctype html>
    <title>javascript闭包</title>
    <meta charset="utf-8"/>
    <script type="text/javascript">
      window.onload = function(){
        var lists = document.getElementsByTagName('li');
         for(var i = 0,len = lists.length; i < len; i++){
            lists[i].onclick = (function(i){
                return function(){
                    alert('点击的是:' + i);
                }
            })(i)
         }
      }
    </script>
    <ul>
      <li id="list1">测试列表</li>
      <li id="list2">测试列表</li>
      <li id="list3">测试列表</li>
      <li id="list4">测试列表</li>
      <li id="list5">测试列表</li>
    </ul>

      2.使用try...catch语句构造的异常闭包

    <!doctype html>
    <title>javascript闭包</title>
    <meta charset="utf-8"/>
    <script type="text/javascript">
      window.onload = function(){
        var lists = document.getElementsByTagName('li');
        for(var i =0,len = lists.length; i < len; i++){
            try{
                throw i;//自定义抛出异常
            }catch(e){
                lists[e].onclick = function(){
                    alert('点击的是:' + e);
                }
            }
        }
      }
    </script>
    <ul>
      <li id="list1">测试列表</li>
      <li id="list2">测试列表</li>
      <li id="list3">测试列表</li>
      <li id="list4">测试列表</li>
      <li id="list5">测试列表</li>
    </ul>

      3.使用with语句造成的对象闭包

    <!doctype html>
    <title>javascript闭包</title>
    <meta charset="utf-8"/>
    <script type="text/javascript">
      window.onload = function(){
        var lists = document.getElementsByTagName('li');
        for(var i =0,len = lists.length; i < len; i++){
            var obj = {value: i}
            with(obj){
                lists[value].onclick = function(){
                    alert('点击的是:' + value)
                }
            }
        }
      }
    </script>
    <ul>
      <li id="list1">测试列表</li>
      <li id="list2">测试列表</li>
      <li id="list3">测试列表</li>
      <li id="list4">测试列表</li>
      <li id="list5">测试列表</li>
    </ul>

    几个经典有用的实例:

      1.自加

    <!doctype html>
    <title>javascript闭包</title>
    <meta charset="utf-8"/>
    <script type="text/javascript">
        /**
        * 自加
        */
        addSelf = (function(){
            var i = 0;
            return function(){
                return i++;
            }
        })();
        alert(addSelf()) //0
        alert(addSelf()) //1
        alert(addSelf()) //2
    </script>

      2.阶乘

    <!doctype html>
    <title>javascript闭包</title>
    <meta charset="utf-8"/>
    <script type="text/javascript">
        /**
        * 阶乘
        */
        var factorial = function(n){
            if(n < 1){
                alert('invalid arguments');
                return 0;
            }
            if(n == 1){
                return 1;
            }else{
                return n*arguments.callee(n-1);
            }
        }
        alert(factorial(3)) //6
        alert(factorial(4)) //24
    </script>

      3.设置/获取 属性值

    <!doctype html>
    <title>javascript闭包</title>
    <meta charset="utf-8"/>
    <script type="text/javascript">
        function User(properties){
            var self = this;
            for(var i in properties){
                (function(){
                    var property = properties[i];
                    self['get' + i] = function(){
                        return property;
                    }
                    self['set' +i] = function(value){
                        property = value;
                    }
                })();
            }
        }
        //测试代码
        var user = new User({
            name:'Bob',
            age: '27'
        });
        
        alert(user.getname()) //Bob
        alert(user.getage()) // 27
        
        user.setname('Mike');
        alert(user.getname()) //Mike
        alert(user.getage()) // 27
        
        user.setage(22);
        alert(user.getname()) //Mike
        alert(user.getage()) // 22
    </script>
  • 相关阅读:
    第一章Python 数据模型
    Numpy 之 where理解
    探析熟悉而又困惑的参数:argc && argv
    python读书笔记
    经典进程的同步问题之——读者写者
    经典进程的同步问题之——哲学家进餐
    冰多多团队博客目录
    团队事后分析
    冰多多团队Gamma阶段发布说明
    gamma测试报告
  • 原文地址:https://www.cnblogs.com/yangkangkang/p/5643022.html
Copyright © 2011-2022 走看看