zoukankan      html  css  js  c++  java
  • 8-JS闭包、回调实例

    1.回调

    javascipt中,函数回调一般用于以下几种场景:

    1.异步执行(例如读取文件,进行HTTP请求)
    2.同步(阻塞)
    3.事件监听和处理
    4.设置超时和时间间隔的方法
    

    异步例子(使用AJAX加载XML文件的示例,并且使用了call()函数,在请求对象(requested object)上下文中调用回调函数。):

    function fn(url, callback){
      var httpRequest;    //创建XHR
      httpRequest = window.XMLHttpRequest ? new XMLHttpRequest() :   //针对IE进行功能性检测
        window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : undefined;
      
      httpRequest.onreadystatechange = function(){
       if(httpRequest.readystate === 4 && httpRequest.status === 200){  //状态判断4和200表示执行该语句
         callback.call(httpRequest.responseXML); 
       }
      };
      httpRequest.open("GET", url);
      httpRequest.send();
    }
     
    fn("text.xml", function(){    //调用函数
     console.log(this);   //此语句后输出
    });
     
    console.log("this will run before the above callback.");  //此语句先输出
    

    异步处理,意味着我们开始请求时,就告诉它们完成之时调用我们的函数。在实际情况中,onreadystatechange事件处理程序还得考虑请求失败的情况,这里我们是假设xml文件存在并且能被浏览器成功加载。这个例子中,异步函数分配给了onreadystatechange事件,因此不会立刻执行。

    同步例子(func1代码执行完成后才执行func2):

    var func1=function(callback){
      //do something.
      (callback && typeof(callback) === "function") && callback();
    }
     
    func1(func2);
      var func2=function(){
    }
    

    提醒:回调函数是个闭包

    2.闭包

    官方释义:闭包是指那些能够访问独立(自由)变量的函数 (变量在本地使用,但定义在一个封闭的作用域中)。换句话说,这些函数可以“记忆”它被创建时候的环境。

    闭包允许将函数与其所操作的某些数据(环境)关连起来。这显然类似于面向对象编程。在面对象编程中,对象允许我们将某些数据(对象的属性)与一个或者多个方法相关联。

    官方实例:假设我们想在页面上添加一些可以调整字号的按钮。一种方法是以像素为单位指定 body 元素的 font-size,然后通过相对的 em 单位设置页面中其它元素(例如页眉)的字号:

    body {
      font-family: Helvetica, Arial, sans-serif;
      font-size: 12px;
    }
    
    h1 {
      font-size: 1.5em;
    }
    
    h2 {
      font-size: 1.2em;
    }
    

    我们的交互式的文本尺寸按钮可以修改 body 元素的 font-size 属性,而由于我们使用相对的单位,页面中的其它元素也会相应地调整。

    以下是 JavaScript:

    function makeSizer(size) {
         return function() {
            document.body.style.fontSize = size + 'px';
        };
    }
        
    var size12 = makeSizer(12);
        
    var size14 = makeSizer(14);
        
    var size16 = makeSizer(16);
    

    size12,size14 和 size16 为将 body 文本相应地调整为 12,14,16 像素的函数。我们可以将它们分别添加到按钮上(这里是链接)。如下所示:

    document.getElementById('size-12').onclick = size12;
    document.getElementById('size-14').onclick = size14;
    document.getElementById('size-16').onclick = size16;
    
    <a href="#" id="size-12">12</a>
    <a href="#" id="size-14">14</a>
    <a href="#" id="size-16">16</a>
    
    function makeSizer(size) {
      return function() {
        document.body.style.fontSize = size + 'px';
      };
    }
    
    var size12 = makeSizer(12);
    var size14 = makeSizer(14);
    var size16 = makeSizer(16);
    
    document.getElementById('size-12').onclick = size12;
    document.getElementById('size-14').onclick = size14;
    document.getElementById('size-16').onclick = size16;
    

    附:闭包的模块模式(使用闭包模拟私有方法)

    var makeCounter = function() {
      var privateCounter = 0;
      function changeBy(val) {
        privateCounter += val;
      }
      return {
        increment: function() {
          changeBy(1);
        },
        decrement: function() {
          changeBy(-1);
        },
        value: function() {
          return privateCounter;
        }
      }  
    };
    
    var Counter1 = makeCounter();
    var Counter2 = makeCounter();
    console.log(Counter1.value()); /* logs 0 */
    Counter1.increment();
    Counter1.increment();
    console.log(Counter1.value()); /* logs 2 */
    Counter1.decrement();
    console.log(Counter1.value()); /* logs 1 */
    console.log(Counter2.value()); /* logs 0 */
    

    此种私有方法不仅仅有利于限制对代码的访问:还提供了管理全局命名空间的强大能力,避免非核心的方法弄乱了代码的公共接口部分。

    注意:不要在循环中创建闭包

  • 相关阅读:
    Android之文件&XML
    Dialog组件
    Android模拟器使用SD卡(2)
    Android 蓝牙开发浅析
    创建和解析XML
    android 读取文件相关
    android 网络编程 HttpGet类和HttpPost类使用详解
    Android模拟器使用SD卡(1)
    Android中控件的OnKeyListener()事件
    [转]Android蓝牙开发浅谈
  • 原文地址:https://www.cnblogs.com/fengxuefei/p/6250535.html
Copyright © 2011-2022 走看看